00001 #include "lugre_prefix.h"
00002 #include "lugre_meshbuffer.h"
00003 #undef min
00004 #undef max
00005 #include <Ogre.h>
00006 #include <map>
00007 #include <string>
00008 #include "lugre_meshshape.h"
00009 using namespace Ogre;
00010
00011 #define DEBUG_MESHBUFFER 0
00012
00013 namespace Lugre {
00014
00015
00016
00017 std::map<std::string,cBufferedMesh*> gBufferedMeshCache;
00018
00019 bool gMeshBuffer_PrintStacktraceOnLoad = false;
00020 void PrintLuaStackTrace ();
00021
00022 cBufferedMesh* GetBufferedMesh (const char* szMeshName) {
00023
00024 cBufferedMesh*& pBufferedMesh = gBufferedMeshCache[szMeshName];
00025 if (pBufferedMesh) return pBufferedMesh;
00026
00027 if (gMeshBuffer_PrintStacktraceOnLoad) {
00028 printf("GetBufferedMesh %s\n",szMeshName);
00029 PrintLuaStackTrace();
00030 }
00031
00032
00033 pBufferedMesh = new cBufferedMesh();
00034 Ogre::MeshPtr pMesh = Ogre::MeshManager::getSingleton().load(szMeshName,
00035 Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
00036 if (!pMesh.isNull()) pBufferedMesh->SetFromMesh(*pMesh);
00037
00038 return pBufferedMesh;
00039 }
00040
00041
00042
00043 cBufferedMesh::cBufferedMesh() : mfBoundRad(0) {}
00044
00045 void cBufferedMesh::SetFromMesh (Ogre::Mesh& pMesh) {
00046 if (DEBUG_MESHBUFFER) printf("cBufferedMesh::SetFromMesh submeshes=%d shared=%d\n",(int)pMesh.getNumSubMeshes(),pMesh.sharedVertexData?1:0);
00047
00048
00049 if (pMesh.sharedVertexData) mBufferedVertexData_Shared.SetFromVertexData(*pMesh.sharedVertexData);
00050
00051
00052 mBufferedSubMeshes.resize(pMesh.getNumSubMeshes());
00053 for (int i=0;i<pMesh.getNumSubMeshes();++i) GetSubMesh(i).SetFromSubMesh(this,*pMesh.getSubMesh(i));
00054
00055
00056
00057
00058
00059 mBounds.setNull();
00060 for (int iSubMesh=0;iSubMesh<mBufferedSubMeshes.size();++iSubMesh) {
00061 cBufferedSubMesh& sub = mBufferedSubMeshes[iSubMesh];
00062 cBufferedVertexData& data = sub.GetUsesShared() ? GetBufferedVertexData_Shared() : sub.GetBufferedVertexData();
00063
00064 for (int iVertex=0;iVertex<data.GetVertexCount();++iVertex) {
00065 Ogre::Vector3 v = data.GetVertexPosVec3(iVertex);
00066 mBounds.merge(v);
00067 }
00068 }
00069
00070 mfBoundRad = mymax(mBounds.getMinimum().length(),mBounds.getMaximum().length());
00071 if (DEBUG_MESHBUFFER) printf("cBufferedMesh::SetFromMesh done\n");
00072 }
00073
00074 int cBufferedMesh::RayPick (const Ogre::Vector3& vRayPos,const Ogre::Vector3& vRayDir,const Ogre::Vector3& vPos,const Ogre::Quaternion& qRot,const Ogre::Vector3& vScale,float* pfHitDist) {
00075
00076 Ogre::Quaternion invrot = qRot.Inverse();
00077 return RayPick((invrot*(vRayPos - vPos))/vScale,(invrot * vRayDir)/ vScale,pfHitDist);
00078 }
00079
00080 int cBufferedMesh::RayPick (const Ogre::Vector3& vRayPos,const Ogre::Vector3& vRayDir,float* pfHitDist) {
00081 if (!Ogre::Ray(vRayPos,vRayDir).intersects(Ogre::Sphere(Ogre::Vector3::ZERO,mfBoundRad + 0.1)).first) return -1;
00082 int iFaceHit = -1;
00083 float myHitDist;
00084 for (int iSubMesh=0;iSubMesh<mBufferedSubMeshes.size();++iSubMesh) {
00085 cBufferedSubMesh& sub = mBufferedSubMeshes[iSubMesh];
00086 cBufferedVertexData& data = sub.GetUsesShared() ? GetBufferedVertexData_Shared() : sub.GetBufferedVertexData();
00087 unsigned int* pIdx = sub.GetIndexData();
00088 unsigned int* pIdxEnd = pIdx + sub.GetIndexCount();
00089 int iFaceNum = 0;
00090 for (;pIdx!=pIdxEnd;pIdx+=3,++iFaceNum) {
00091 if (IntersectRayTriangle(vRayPos,vRayDir,
00092 data.GetVertexPosVec3(pIdx[0]),
00093 data.GetVertexPosVec3(pIdx[1]),
00094 data.GetVertexPosVec3(pIdx[2]),&myHitDist)) {
00095 if (iFaceHit == -1 || myHitDist < *pfHitDist) { *pfHitDist = myHitDist; iFaceHit = iFaceNum; }
00096 }
00097 }
00098 }
00099 return iFaceHit;
00100 }
00101
00102
00103
00104 cBufferedVertexData::cBufferedVertexData() : miVertexCount(0) {}
00105
00106 cBufferedVertexData::~cBufferedVertexData() {
00108 for (int i=0;i<mDataBuffers.size();++i) free(mDataBuffers[i]);
00109 mDataBuffers.clear();
00110 mDataBufferVertexSize.clear();
00111 }
00112
00113 void cBufferedVertexData::SetFromVertexData (const Ogre::VertexData& pVertexData) {
00114 assert(mDataBuffers.size() == 0 && "do not init more than once");
00115 assert(mDataBufferVertexSize.size() == 0 && "do not init more than once");
00116
00117
00118 if (DEBUG_MESHBUFFER) printf("cBufferedVertexData::SetFromVertexData vertexdecl\n");
00119 mpVertexDecl = pVertexData.vertexDeclaration ? pVertexData.vertexDeclaration->clone() : 0;
00120
00121
00122 miVertexCount = pVertexData.vertexCount;
00123
00124
00125 int iBufferCount = mpVertexDecl ? (mpVertexDecl->getMaxSource()+1) : 0;
00126 if (DEBUG_MESHBUFFER) printf("cBufferedVertexData::SetFromVertexData buffers:%d %d\n",iBufferCount,(int)pVertexData.vertexBufferBinding->getBufferCount());
00127 for (int iBuffer=0;iBuffer<iBufferCount;++iBuffer) {
00128
00129 HardwareVertexBufferSharedPtr vbuf = pVertexData.vertexBufferBinding->getBuffer(iBuffer);
00130
00131
00132 int iDataSize = miVertexCount * vbuf->getVertexSize();
00133 if (DEBUG_MESHBUFFER) printf("cBufferedVertexData::SetFromVertexData buffer[%d] vsize=%d\n",iBuffer,(int)vbuf->getVertexSize());
00134 char* pRAMBuffer = (char*)malloc(iDataSize);
00135 mDataBuffers.push_back(pRAMBuffer);
00136 mDataBufferVertexSize.push_back(vbuf->getVertexSize());
00137
00138
00139 vbuf->readData(0,iDataSize,pRAMBuffer);
00140 }
00141
00142
00143 if (DEBUG_MESHBUFFER) printf("cBufferedVertexData::SetFromVertexData prepare quick access\n");
00144 SetQuickDataFromSemantic(mQuickPos,Ogre::VES_POSITION);
00145 SetQuickDataFromSemantic(mQuickTexCoord,Ogre::VES_TEXTURE_COORDINATES);
00146 if (DEBUG_MESHBUFFER) printf("cBufferedVertexData::SetFromVertexData done\n");
00147 }
00148
00149 void cBufferedVertexData::SetQuickDataFromSemantic (cQuickData& pQuickData,const Ogre::VertexElementSemantic sem,const int i) {
00150 assert(!pQuickData.mpFirst && !pQuickData.miOffsetToNext && "do not init more than once");
00151
00152
00153 const Ogre::VertexElement* elem = mpVertexDecl ? mpVertexDecl->findElementBySemantic(sem,i) : 0;
00154 if (!elem) return;
00155
00156
00157 unsigned short iSource = elem->getSource();
00158 assert(iSource < mDataBuffers.size());
00159
00160
00161 pQuickData.mpFirst = mDataBuffers[iSource] + elem->getOffset();
00162 pQuickData.miOffsetToNext = mpVertexDecl->getVertexSize(iSource);
00163 }
00164
00165
00166
00167
00168
00169
00170 cBufferedSubMesh::cBufferedSubMesh() : mbUseSharedVertexData(false), mpParent(0) {}
00171
00172 void cBufferedSubMesh::TransformTexCoords (const float u0,const float v0,const float u1,const float v1) {
00173 if (GetUsesShared()) { printf("ERROR: cBufferedSubMesh::TransformTexCoords : shared vertex data not supported (oldmat=%s)\n",msMatName.c_str()); return; }
00174 float ud = u1 - u0;
00175 float vd = v1 - v0;
00176 for (int i=0;i<GetVertexCount();++i) {
00177 float* p = mBufferedVertexData.GetVertexTexCoord(i);
00178 p[0] = u0 + ud*mymax(0.0,mymin(1.0,p[0]));
00179 p[1] = v0 + vd*mymax(0.0,mymin(1.0,p[1]));
00180 }
00181 }
00182
00183 void cBufferedSubMesh::SetMatName (const char* szMatName) {
00184 msMatName = szMatName;
00185 try {
00186 mpMat = Ogre::MaterialManager::getSingleton().getByName(msMatName);
00187 } catch (...) {}
00188 }
00189
00190 void cBufferedSubMesh::SetFromSubMesh (cBufferedMesh* pParent,Ogre::SubMesh& pSubMesh) {
00191 if (DEBUG_MESHBUFFER) printf("cBufferedSubMesh::SetFromSubMesh\n");
00192
00193
00194 mpParent = pParent;
00195
00196
00197 SetMatName(pSubMesh.getMaterialName().c_str());
00198
00199
00200 mbUseSharedVertexData = pSubMesh.useSharedVertices;
00201 if (!mbUseSharedVertexData) {
00202 if (pSubMesh.vertexData)
00203 mBufferedVertexData.SetFromVertexData(*pSubMesh.vertexData);
00204 else printf("cBufferedSubMesh::SetFromSubMesh warning, empty submesh vertex data\n");
00205 }
00206 if (DEBUG_MESHBUFFER) printf("cBufferedSubMesh::SetFromSubMesh mat=%s mbUseSharedVertexData=%d\n",msMatName.c_str(),mbUseSharedVertexData?1:0);
00207
00208
00209 Ogre::VertexElementType iPreferredColourFormat = Root::getSingleton().getRenderSystem()->getColourVertexElementType();
00210 if (DEBUG_MESHBUFFER) printf("cBufferedSubMesh::SetFromSubMesh hash start\n");
00211 if (mBufferedVertexData.GetVertexDecl()) {
00212 Ogre::StringUtil::StrStreamType str;
00213 bool bHasColour = false;
00214 str << msMatName << "|";
00215
00216 const Ogre::VertexDeclaration::VertexElementList &elemList = mBufferedVertexData.GetVertexDecl()->getElements();
00217 Ogre::VertexDeclaration::VertexElementList::const_iterator i;
00218 for (i = elemList.begin(); i != elemList.end(); ++i) {
00219 const Ogre::VertexElement &element = *i;
00220 str << element.getSource() << "|";
00221 str << element.getSemantic() << "|";
00222 str << element.getType() << "|";
00223 if (element.getSemantic() == Ogre::VES_DIFFUSE) bHasColour = true;
00224 }
00225 msFormatHash = str.str();
00226 if (bHasColour) {
00227 msFormatHashWithColour = msFormatHash;
00228 } else {
00229
00230 str << 0 << "|";
00231 str << Ogre::VES_DIFFUSE << "|";
00232 str << iPreferredColourFormat << "|";
00233 msFormatHashWithColour = str.str();
00234 }
00235 }
00236 if (DEBUG_MESHBUFFER) printf("cBufferedSubMesh::SetFromSubMesh hash done\n");
00237
00238
00239 IndexData* index_data = pSubMesh.indexData;
00240 HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
00241
00242 mIndexData.clear();
00243 mIndexData.reserve(index_data->indexCount);
00244 if (DEBUG_MESHBUFFER) printf("cBufferedSubMesh::SetFromSubMesh indices=%d\n",(int)index_data->indexCount);
00245 if (ibuf->getType() == HardwareIndexBuffer::IT_32BIT) {
00246 ::uint32* pReader = static_cast< ::uint32*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
00247 for (int i=0;i<index_data->indexCount;++i) mIndexData.push_back(static_cast<unsigned int>(pReader[i]));
00248 } else {
00249 ::uint16* pReader = static_cast< ::uint16*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
00250 for (int i=0;i<index_data->indexCount;++i) mIndexData.push_back(static_cast<unsigned int>(pReader[i]));
00251 }
00252 ibuf->unlock();
00253 if (DEBUG_MESHBUFFER) printf("cBufferedSubMesh::SetFromSubMesh done\n");
00254 }
00255
00256
00257
00258 };