#include "ivmeshdata.h" #include "ivreader.h" IVMeshData::IVMeshData() { vertices = normals = texCoords = indices = normalIndices = texCoordIndices = NULL; vcnt = ncnt = tcnt = icnt = nicnt = ticnt = 0; roType = IV_ROT_INVALID; boundingBox = NULL; } IVMeshData::~IVMeshData() { } void IVMeshData::collapse() { if (indices != NULL) delete [] indices; if (vertices != NULL) delete [] vertices; if (normals != NULL) delete [] normals; if (texCoords != NULL) delete [] texCoords; if (normalIndices != NULL) delete [] normalIndices; if (texCoordIndices != NULL) delete [] texCoordIndices; if (boundingBox != NULL) delete boundingBox; indices = vertices = normals = texCoords = normalIndices = texCoords = NULL; boundingBox = NULL; } int IVMeshData::getSeparatorCnt(Ogre::Real *data, int end) { int cnt = 0; for (int i=0; i < end; i++) if (data[i] < 0.f) cnt++; return cnt; } Ogre::AxisAlignedBox *IVMeshData::calcBoundingBox() { if ((vertices == NULL) || (vcnt <=0)) return new Ogre::AxisAlignedBox(0, 0, 0, 0, 0, 0); Ogre::Real x, y, z, minX, minY, minZ, maxX, maxY, maxZ; minX = minY = minZ = 999999; maxX = maxY = maxZ = -999999; for (int i=0; i x) minX = x; if (maxX < x) maxX = x; y = vertices[i*3+1]; if (minY > y) minY = y; if (maxY < y) maxY = y; z = vertices[i*3+2]; if (minZ > z) minZ = z; if (maxZ < z) maxZ = z; } return new Ogre::AxisAlignedBox(minX, minY, minZ, maxX, maxY, maxZ); } Ogre::Real *IVMeshData::expandTriangleStripIndices(Ogre::Real *indices, int icnt, int *icntOut) { if (indices[icnt-1] >= 0.0) *icntOut = (icnt+1 - 3*(getSeparatorCnt(indices, icnt)+1))*3; else *icntOut = (icnt - 3*getSeparatorCnt(indices, icnt))*3; Ogre::Real *indOut = new Ogre::Real[*icntOut]; int triangleCnt = 0, tc = 0; for (int i=2; i < icnt; i++) { if (indices[i] >= 0) { if (tc % 2 == 0) { indOut[triangleCnt*3] = indices[i-2]; indOut[triangleCnt*3+1] = indices[i-1]; indOut[triangleCnt*3+2] = indices[i]; } else { indOut[triangleCnt*3] = indices[i]; indOut[triangleCnt*3+1] = indices[i-1]; indOut[triangleCnt*3+2] = indices[i-2]; } triangleCnt++; tc++; } else { i += 2; tc = 0; } } return indOut; } int IVMeshData::getNextFaceSize(int start) { for (int i=start; i < icnt; i++) { if (indices[i] < 0.f) return i - start; } return icnt - start; } Ogre::Real *IVMeshData::expandFaceSetIndices(Ogre::Real *indices, int icnt, int *icntOut) { if (indices[icnt-1] >= 0.0) *icntOut = (icnt+1 - 3*(getSeparatorCnt(indices, icnt)+1))*3; else *icntOut = (icnt - 3*getSeparatorCnt(indices, icnt))*3; Ogre::Real *indOut = new Ogre::Real[*icntOut]; int index = 0, size = 0; for (int i=0; i < icnt; i++) { if ((size = getNextFaceSize(i)) < 3) break; for (int j=0; j < size-2; j++) { indOut[index] = indices[i]; index++; indOut[index] = indices[i+1+j]; index++; indOut[index] = indices[i+2+j]; index++; } i = i + size; } return indOut; } IVMeshData *IVMeshData::expand() { using namespace Ogre; IVMeshData *mDataOut = new IVMeshData(); mDataOut->boundingBox = calcBoundingBox(); if ((vertices == NULL) || (vcnt <= 0) || (indices == NULL) || (icnt <= 0)) { if (IVReader::IVLog != NULL) { std::string message = "Expand-Error: ((vertices == NULL) || (vcnt <= 0) || (indices == NULL) || (icnt <= 0))"; IVReader::IVLog->logMessage(message); } return mDataOut; } bool nOk, tOk, niOk, tiOk, nperv, tperv; nOk = ((normals != NULL) && (ncnt > 0)); tOk = ((texCoords != NULL) && (tcnt > 0)); nperv = (ncnt == vcnt) && (nicnt != icnt); tperv = (tcnt*3 == vcnt*2) && (ticnt != icnt); if ((nOk && !nperv) || (tOk && !tperv)) { niOk = ((normalIndices != NULL) && (nicnt == icnt)); tiOk = ((texCoordIndices != NULL) && (ticnt == icnt)); if (!nperv && nOk && !niOk) nOk = false; if (!tperv && tOk && !tiOk) tOk = false; int sepcnt = getSeparatorCnt(indices, icnt); mDataOut->icnt = icnt; mDataOut->vcnt = (icnt - sepcnt)*3; mDataOut->vertices = new Real[mDataOut->vcnt]; if (nOk) { mDataOut->ncnt = mDataOut->vcnt; mDataOut->normals = new Real[mDataOut->ncnt]; } if (tOk) { mDataOut->tcnt = (icnt - sepcnt)*2; mDataOut->texCoords = new Real[mDataOut->tcnt]; } mDataOut->indices = new Real[mDataOut->icnt]; int index = 0; for (int i=0; i < icnt; i++) { if (indices[i] >= 0.f) { mDataOut->vertices[index*3] = vertices[(int)indices[i]*3]; mDataOut->vertices[index*3+1] = vertices[(int)indices[i]*3+1]; mDataOut->vertices[index*3+2] = vertices[(int)indices[i]*3+2]; if (nOk) { if (nperv) { mDataOut->normals[index*3] = normals[(int)indices[i]*3]; mDataOut->normals[index*3+1] = normals[(int)indices[i]*3+1]; mDataOut->normals[index*3+2] = normals[(int)indices[i]*3+2]; } else { mDataOut->normals[index*3] = normals[(int)normalIndices[i]*3]; mDataOut->normals[index*3+1] = normals[(int)normalIndices[i]*3+1]; mDataOut->normals[index*3+2] = normals[(int)normalIndices[i]*3+2]; } } if (tOk) { if (tperv) { mDataOut->texCoords[index*2] = texCoords[(int)indices[i]*2]; mDataOut->texCoords[index*2+1] = texCoords[(int)indices[i]*2+1]; } else { mDataOut->texCoords[index*2] = texCoords[(int)texCoordIndices[i]*2]; mDataOut->texCoords[index*2+1] = texCoords[(int)texCoordIndices[i]*2+1]; } } mDataOut->indices[i] = index; index++; } else mDataOut->indices[i] = indices[i]; } } else { mDataOut->icnt = icnt; mDataOut->indices = new Real[mDataOut->icnt]; memcpy(mDataOut->indices, indices, mDataOut->icnt*sizeof(Real)); mDataOut->vcnt = vcnt; mDataOut->vertices = new Real[mDataOut->vcnt]; memcpy(mDataOut->vertices, vertices, mDataOut->vcnt*sizeof(Real)); if (nOk) { mDataOut->ncnt = ncnt; mDataOut->normals = new Real[mDataOut->ncnt]; memcpy(mDataOut->normals, normals, mDataOut->ncnt*sizeof(Real)); } if (tOk) { mDataOut->tcnt = tcnt; mDataOut->texCoords = new Real[mDataOut->tcnt]; memcpy(mDataOut->texCoords, texCoords, mDataOut->tcnt*sizeof(Real)); } } int icntNew = 0; Real *indicesNew = NULL; mDataOut->roType = roType; if (mDataOut->roType == IV_ROT_TRIANGLE_STRIP) { indicesNew = expandTriangleStripIndices(mDataOut->indices, mDataOut->icnt, &icntNew); } else if (mDataOut->roType == IV_ROT_FACE_SET) { indicesNew = expandFaceSetIndices(mDataOut->indices, mDataOut->icnt, &icntNew); } else { return mDataOut; } delete [] mDataOut->indices; mDataOut->indices = indicesNew; mDataOut->icnt = icntNew; return mDataOut; }