📄 mobmodel.cpp
字号:
// ==========================================================================================================
//
// BREW v2.0+ OPENGLES MICROENGINE
//
// ----------------------------------------
//
// Written by Vander Nunes
//
// ==========================================================================================================
#include "mobmodel.h"
#include "math3d.h"
#include "vfs.h"
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
CMobModel::CMobModel()
{
m_bZWrite = TRUE;
m_bBackCull = TRUE;
m_pVertices = NULL;
#if INC_NORMALS
m_pNormals = NULL;
#if INC_ENVMAP
m_pEnvNormals = NULL;
m_pEnvTexCoords = NULL;
#endif
#endif
m_pFaces = NULL;
m_pColors = NULL;
m_pTexCoords = NULL;
m_dwVertexCount = m_dwFaceCount = m_dwTexCoords = 0;
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
CMobModel::~CMobModel()
{
if (m_pVertices) delete[] m_pVertices;
#if INC_NORMALS
if (m_pNormals) delete[] m_pNormals;
#if INC_ENVMAP
DeletePtrArray(m_pEnvNormals);
DeletePtrArray(m_pEnvTexCoords);
#endif
#endif
if (m_pFaces) delete[] m_pFaces;
if (m_pColors) delete[] m_pColors;
if (m_pTexCoords) delete[] m_pTexCoords;
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
boolean CMobModel::Load(AEEApplet* pApplet, char *szPakFile, char *szFile, float fXScale, float fYScale, float fZScale)
{
//DBGPRINTF("Loading MobModel: %s", szFile);
uint32 i;
CVfs Vfs;
if (!Vfs.Unpack(szPakFile, szFile, pApplet))
return FALSE;
//
// read flag if exported from a 3DS file (if so, will need to negate V coordinate map)
// 0 == not converted from a 3DS (or 3DSMAX) model
// 1 == converted from a 3DS (or 3DSMAX) model
byte bFrom3DS;
Vfs.Read((void*)&bFrom3DS, 1);
//
// read vertices
//
Vfs.Read((void*)&m_dwVertexCount, sizeof(dword));
// allocate space
m_pVertices = new int[m_dwVertexCount * 3];
m_pColors = new dword[m_dwVertexCount * 4];
m_pTexCoords = new dword[m_dwVertexCount * 2];
#if INC_NORMALS
m_pNormals = new int[m_dwVertexCount * 3];
#if INC_ENVMAP
m_pEnvNormals = new int[m_dwVertexCount * 3];
m_pEnvTexCoords = new dword[m_dwVertexCount * 2];
#endif
#endif
// reset bounding sphere and bounding box
m_dwBSphere = 0;
VectorSet(m_BBMin, ITOX(999999), ITOX(999999), ITOX(999999));
VectorSet(m_BBMax, ITOX(-999999), ITOX(-999999), ITOX(-999999));
// load vertices
for (i = 0; i < m_dwVertexCount; i ++)
{
int j;
int idx2 = i * 2;
int idx3 = i * 3;
int idx4 = i * 4;
// read
Vfs.Read((void*)&m_pVertices[idx3], sizeof(int) * 3);
// scale
m_pVertices[idx3 + 0] = (int)(m_pVertices[idx3 + 0] * fXScale);
m_pVertices[idx3 + 1] = (int)(m_pVertices[idx3 + 1] * fYScale);
m_pVertices[idx3 + 2] = (int)(m_pVertices[idx3 + 2] * fZScale);
// update bounding sphere
if ((dword)ABS(m_pVertices[idx3 + 0]) > m_dwBSphere) m_dwBSphere = ABS(m_pVertices[idx3 + 0]);
if ((dword)ABS(m_pVertices[idx3 + 1]) > m_dwBSphere) m_dwBSphere = ABS(m_pVertices[idx3 + 1]);
if ((dword)ABS(m_pVertices[idx3 + 2]) > m_dwBSphere) m_dwBSphere = ABS(m_pVertices[idx3 + 2]);
// update bounding box
if (m_pVertices[idx3 + 0] < m_BBMin[0]) m_BBMin[0] = m_pVertices[idx3 + 0];
if (m_pVertices[idx3 + 1] < m_BBMin[1]) m_BBMin[1] = m_pVertices[idx3 + 1];
if (m_pVertices[idx3 + 2] < m_BBMin[2]) m_BBMin[2] = m_pVertices[idx3 + 2];
if (m_pVertices[idx3 + 0] > m_BBMax[0]) m_BBMax[0] = m_pVertices[idx3 + 0];
if (m_pVertices[idx3 + 1] > m_BBMax[1]) m_BBMax[1] = m_pVertices[idx3 + 1];
if (m_pVertices[idx3 + 2] > m_BBMax[2]) m_BBMax[2] = m_pVertices[idx3 + 2];
// color
byte c;
for (j = 0; j < 4; j ++)
{
Vfs.Read((void*)&c, sizeof(byte));
// invert from rgb to bgr
m_pColors[idx4 + j] = ((dword)c) << 8; // convert color component to 16.16 fp OGLES format
}
// uv
for (j = 0; j < 2; j ++)
{
Vfs.Read((void*)&m_pTexCoords[idx2 + j], sizeof(dword));
}
// ### hack needed because of v coordinate being inverted by the 3ds converter
if (bFrom3DS == 1)
// this model was converted from 3DS or 3DSMAX, need to negate V mapping
m_pTexCoords[idx2 + 1] = ITOX(1) - m_pTexCoords[idx2 + 1]; // invert v
}
//
// read faces
//
Vfs.Read((void*)&m_dwFaceCount, sizeof(dword));
m_pFaces = new word[m_dwFaceCount * 3];
for (i = 0; i < m_dwFaceCount; i ++)
{
int j;
// vertex indexes
for (j = 0; j < 3; j ++)
{
dword tmp;
Vfs.Read((void*)&tmp, sizeof(dword));
m_pFaces[i * 3 + j] = (word)tmp;
}
}
//
// ### IMPORTANT:
// the latest mob model format includes
// DWORD LightCount ; Number of billboarded lights in the object
// DWORD X Y Z ; Coordinates (16:16) for each embedded light
// (but at this moment we're ignoring lights -- support to be added later)
//
#if INC_NORMALS
RecalculateNormals();
#endif
Vfs.Finish();
return TRUE;
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
void CMobModel::AllocSpace(uint32 dwVertices, uint32 dwFaces)
{
m_dwVertexCount = dwVertices;
m_dwFaceCount = dwFaces;
m_dwTexCoords = m_dwVertexCount;
m_pVertices = new int[m_dwVertexCount * 3];
m_pColors = new dword[m_dwVertexCount * 4];
m_pTexCoords = new dword[m_dwTexCoords * 2];
m_pFaces = new word[m_dwFaceCount * 3];
#if INC_NORMALS
m_pNormals = new int[m_dwVertexCount * 3];
#if INC_ENVMAP
m_pEnvNormals = new int[m_dwVertexCount * 3];
m_pEnvTexCoords = new dword[m_dwTexCoords * 2];
#endif
#endif
}
// -------------------------------------------------------------------------------------------
//
// Generate a sphere with user-specified divisions and material.
//
// -------------------------------------------------------------------------------------------
void CMobModel::MakeSphere(float fRadius, word wDivr, word wDivh, boolean bUseUVHack)
{
uint32 x,y;
float a,da,yp,ya,yda,yf;
float U,V,dU,dV;
m_dwBSphere = FTOX(fRadius);
if (wDivr < 3) wDivr = 3;
if (wDivh < 3) wDivh = 3;
uint32 NF = (wDivr * 2) + ((wDivh - 3) * 2 * wDivr);
uint32 NV = ((wDivh - 2) * (wDivr + 1) + 2);
AllocSpace(NV, NF);
NF *= 3;
NV *= 3;
// top vertex
m_pVertices[0] = 0;
m_pVertices[1] = FTOX(fRadius);
m_pVertices[2] = 0;
// bottom vertex
m_pVertices[3] = 0;
m_pVertices[4] = FTOX(-fRadius);
m_pVertices[5] = 0;
uint32 dwVIdx = 6;
ya = 0;
yda = PI/(wDivh-1);
da = (2*PI)/wDivr;
// create all sphere vertices at once
for (y = 0; y < (uint32)wDivh-2; y++)
{
ya += yda;
yp = (float)cos(ya)*fRadius;
yf = (float)sin(ya)*fRadius;
a = 0;
for (x = 0; x < wDivr; x++)
{
m_pVertices[dwVIdx+0] = FTOX((float)cos(a)*yf);
m_pVertices[dwVIdx+1] = FTOX(yp);
m_pVertices[dwVIdx+2] = FTOX((float)sin(a)*yf);
dwVIdx += 3;
// hack: create the last vertices at the same point,
// to avoid UV mapping limitation (can't assign a second UV for the same vertice).
if (x==(uint32)(wDivr-1))
{
m_pVertices[dwVIdx+0] = m_pVertices[(y*(wDivr+1)+2)*3+0];
m_pVertices[dwVIdx+1] = m_pVertices[(y*(wDivr+1)+2)*3+1];
m_pVertices[dwVIdx+2] = m_pVertices[(y*(wDivr+1)+2)*3+2];
dwVIdx += 3;
}
a += da;
}
}
a = 0;
U = 1;
dU = -1.0f/wDivr;
dV = V = 1.0f/wDivh;
uint32 dwFIdx = 0;
// create top faces
for (x = 0; x < wDivr; x++)
{
int v[3] = { 0, (2+x+1), (2+x) };
m_pFaces[dwFIdx++] = v[0];
m_pFaces[dwFIdx++] = v[1];
m_pFaces[dwFIdx++] = v[2];
m_pTexCoords[v[0]*2] = FTOX(U);
m_pTexCoords[v[0]*2+1] = FTOX(0);
m_pTexCoords[v[1]*2] = FTOX(U+dU);
m_pTexCoords[v[1]*2+1] = FTOX(V);
m_pTexCoords[v[2]*2] = FTOX(U);
m_pTexCoords[v[2]*2+1] = FTOX(V);
U += dU;
}
da = 1.0f/(wDivr+1);
int offv = 2;
// create main body faces
for (x = 0; x < (uint32)(wDivh-3); x++)
{
U = 1;
for (y = 0; y < wDivr; y++)
{
int v[3] = { (offv+y), (offv+(wDivr+1)+y+1), (offv+y+(wDivr+1)) };
m_pFaces[dwFIdx++] = v[0];
m_pFaces[dwFIdx++] = v[1];
m_pFaces[dwFIdx++] = v[2];
m_pTexCoords[v[0]*2] = FTOX(U);
m_pTexCoords[v[0]*2+1] = FTOX(V);
m_pTexCoords[v[1]*2] = FTOX(U+dU);
m_pTexCoords[v[1]*2+1] = FTOX(V+dV);
m_pTexCoords[v[2]*2] = FTOX(U);
m_pTexCoords[v[2]*2+1] = FTOX(V+dV);
int vv[3] = { (offv+y), (offv+y+1), (offv+y+1+(wDivr+1)) };
m_pFaces[dwFIdx++] = vv[0];
m_pFaces[dwFIdx++] = vv[1];
m_pFaces[dwFIdx++] = vv[2];
m_pTexCoords[vv[0]*2] = FTOX(U);
m_pTexCoords[vv[0]*2+1] = FTOX(V);
m_pTexCoords[vv[1]*2] = FTOX(U+dU);
m_pTexCoords[vv[1]*2+1] = FTOX(V);
m_pTexCoords[vv[2]*2] = FTOX(U+dU);
m_pTexCoords[vv[2]*2+1] = FTOX(V+dV);
U += dU;
}
V += dV;
offv += wDivr+1;
}
int s = m_dwVertexCount - wDivr - 1;
U = 1;
// create bottom faces
for (x = 0; x < wDivr; x++)
{
int v[3] = { 1, (s+x), (s+x+1) };
m_pFaces[dwFIdx++] = v[0];
m_pFaces[dwFIdx++] = v[1];
m_pFaces[dwFIdx++] = v[2];
m_pTexCoords[v[0]*2] = FTOX(U);
m_pTexCoords[v[0]*2+1] = FTOX(1.0f);
m_pTexCoords[v[1]*2] = FTOX(U);
m_pTexCoords[v[1]*2+1] = FTOX(V);
m_pTexCoords[v[2]*2] = FTOX(U+dU);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -