lugre_meshshape.cpp
Go to the documentation of this file.00001 #include "lugre_prefix.h"
00002 #include "lugre_meshshape.h"
00003 #undef min
00004 #undef max
00005 #include <Ogre.h>
00006 #include <assert.h>
00007 using namespace Ogre;
00008
00009 namespace Lugre {
00010
00011 std::map<std::string,MeshShape*> gMeshShapeCache;
00012
00013 void UnloadMeshShape (const char* szMeshName) {
00014 MeshShape*& pShape = gMeshShapeCache[szMeshName];
00015 if (pShape) { delete pShape; pShape = 0; }
00016 }
00017
00018 MeshShape* MeshShape::GetMeshShape (Ogre::Entity* pEntity) {
00019 if (!pEntity) return 0;
00020 Ogre::MeshPtr pMesh = pEntity->getMesh();
00021 assert(!pMesh.isNull() && "entity has no mesh");
00022 if (pMesh.isNull()) return 0;
00023
00024
00025 MeshShape*& pShape = gMeshShapeCache[pMesh->getName()];
00026 if (pShape) { pShape->Update(pEntity); return pShape; }
00027
00028
00029 pShape = new MeshShape(pMesh);
00030 pShape->Update(pEntity);
00031 return pShape;
00032 }
00033
00034 MeshShape::MeshShape (Ogre::MeshPtr pMesh) : mbInitialised(false), mpMesh(pMesh), mvMin(0,0,0), mvMax(0,0,0) {}
00035 MeshShape::~MeshShape () {}
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00059 bool IntersectRayTriangle (const Vector3& ray_origin,const Vector3& ray_dir,const Vector3& a,const Vector3& b,const Vector3& c,float* pfHitDist,float* pfABC) {
00060
00061 Vector3 kDiff = ray_origin - a;
00062 Vector3 kEdge1 = b - a;
00063 Vector3 kEdge2 = c - a;
00064 Vector3 kNormal = kEdge1.crossProduct(kEdge2);
00065 Real ZERO_TOLERANCE = 0.1E-6;
00066
00067
00068
00069
00070
00071
00072 Real fDdN = ray_dir.dotProduct(kNormal);
00073 Real fSign;
00074 if (fDdN > ZERO_TOLERANCE)
00075 {
00076 fSign = (Real)1.0;
00077 }
00078 else if (fDdN < -ZERO_TOLERANCE)
00079 {
00080 fSign = (Real)-1.0;
00081 fDdN = -fDdN;
00082 }
00083 else
00084 {
00085
00086
00087 return false;
00088 }
00089
00090 Real fDdQxE2 = fSign*ray_dir.dotProduct(kDiff.crossProduct(kEdge2));
00091 if (fDdQxE2 >= (Real)0.0)
00092 {
00093 Real fDdE1xQ = fSign*ray_dir.dotProduct(kEdge1.crossProduct(kDiff));
00094 if (fDdE1xQ >= (Real)0.0)
00095 {
00096 if (fDdQxE2 + fDdE1xQ <= fDdN)
00097 {
00098
00099 Real fQdN = -fSign*kDiff.dotProduct(kNormal);
00100 if (fQdN >= (Real)0.0)
00101 {
00102
00103 if (pfABC || pfHitDist) {
00104 Real fInv = ((Real)1.0)/fDdN;
00105 if (pfHitDist) *pfHitDist = fQdN*fInv;
00106 if (pfABC) {
00107 pfABC[1] = fDdQxE2*fInv;
00108 pfABC[2] = fDdE1xQ*fInv;
00109 pfABC[0] = (Real)1.0 - pfABC[1] - pfABC[2];
00110 }
00111 }
00112 return true;
00113 }
00114
00115 }
00116
00117 }
00118
00119 }
00120
00121
00122 return false;
00123 }
00124
00125
00126
00127
00132 void MeshShape::Update (Ogre::Entity *pEntity) {
00133
00134 if (mpMesh.isNull()) return;
00135 if (pEntity && mbInitialised && !pEntity->hasSkeleton()) return;
00136 mbInitialised = true;
00137
00138
00139
00140
00141
00142 mlVertices.clear();
00143 mlIndices.clear();
00144
00145 bool added_shared = false;
00146 size_t current_offset = 0;
00147 size_t shared_offset = 0;
00148 size_t next_offset = 0;
00149 size_t index_offset = 0;
00150 int numOfSubs = 0;
00151
00152
00153 bool useSoftwareBlendingVertices = pEntity && pEntity->hasSkeleton();
00154
00155 if (useSoftwareBlendingVertices)
00156 {
00157 pEntity->_updateAnimation();
00158 }
00159
00160
00161 for ( size_t i = 0; i < mpMesh->getNumSubMeshes(); ++i) {
00162 SubMesh* submesh = mpMesh->getSubMesh(i);
00163 bool useSharedVertices = submesh->useSharedVertices;
00164
00165
00166
00167
00168 const VertexData * vertex_data;
00169 if(useSoftwareBlendingVertices)
00170 vertex_data = useSharedVertices ? pEntity->_getSkelAnimVertexData() : pEntity->getSubEntity(i)->_getSkelAnimVertexData();
00171 else vertex_data = useSharedVertices ? mpMesh->sharedVertexData : submesh->vertexData;
00172
00173 if((!useSharedVertices)||(useSharedVertices && !added_shared))
00174 {
00175 if(useSharedVertices)
00176 {
00177 added_shared = true;
00178 shared_offset = current_offset;
00179 }
00180
00181 const VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
00182
00183 HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
00184
00185 unsigned char* vertex =
00186 static_cast<unsigned char*>(vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
00187
00188
00189
00190
00191 float* pReal;
00192
00193 mlVertices.reserve(mlVertices.size()+vertex_data->vertexCount);
00194 for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
00195 {
00196 posElem->baseVertexPointerToElement(vertex, &pReal);
00197 if (mlVertices.size() == 0) {
00198 mvMin.x = mvMax.x = pReal[0];
00199 mvMin.y = mvMax.y = pReal[1];
00200 mvMin.z = mvMax.z = pReal[2];
00201 } else {
00202 if (mvMin.x > pReal[0]) mvMin.x = pReal[0];
00203 if (mvMin.y > pReal[1]) mvMin.y = pReal[1];
00204 if (mvMin.z > pReal[2]) mvMin.z = pReal[2];
00205 if (mvMax.x < pReal[0]) mvMax.x = pReal[0];
00206 if (mvMax.y < pReal[1]) mvMax.y = pReal[1];
00207 if (mvMax.z < pReal[2]) mvMax.z = pReal[2];
00208 }
00209 mlVertices.push_back(Vector3(pReal[0],pReal[1],pReal[2]));
00210 }
00211
00212 vbuf->unlock();
00213 next_offset += vertex_data->vertexCount;
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 IndexData* index_data = submesh->indexData;
00228 size_t numTris = index_data->indexCount / 3;
00229 HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
00230
00231 bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT);
00232
00233 ::uint32 *pLong = static_cast< ::uint32*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
00234 ::uint16* pShort = reinterpret_cast< ::uint16*>(pLong);
00235
00236 size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset;
00237
00238 mlIndices.reserve(mlIndices.size()+3*numTris);
00239 if ( use32bitindexes )
00240 {
00241 for ( size_t k = 0; k < numTris*3; ++k)
00242 {
00243 mlIndices.push_back(pLong[k] + static_cast<int>(offset));
00244 }
00245 }
00246 else
00247 {
00248 for ( size_t k = 0; k < numTris*3; ++k)
00249 {
00250 mlIndices.push_back(static_cast<int>(pShort[k]) + static_cast<int>(offset));
00251 }
00252 }
00253
00254 ibuf->unlock();
00255
00256 current_offset = next_offset;
00257 }
00258
00259
00260 }
00261
00262
00263 void MeshShape::RayIntersect (const Ogre::Vector3& ray_origin,const Ogre::Vector3& ray_dir,std::vector<std::pair<float,int> > &pHitList) {
00264 if (mpMesh.isNull()) return;
00265 Vector3 vMid = 0.5*(mvMin + mvMax);
00266 float fRad = mymax((mvMin-vMid).length(),(mvMax-vMid).length());
00267 if (!Ogre::Ray(ray_origin,ray_dir).intersects(Ogre::Sphere(vMid,fRad + 0.1)).first) return;
00268 float myHitDist;
00269 for (int i=0;i<mlIndices.size();i+=3) {
00270 if (IntersectRayTriangle(ray_origin,ray_dir,
00271 mlVertices[mlIndices[i+0]],
00272 mlVertices[mlIndices[i+1]],
00273 mlVertices[mlIndices[i+2]],&myHitDist)) {
00274 pHitList.push_back(std::make_pair(myHitDist,i/3));
00275 }
00276 }
00277 }
00278
00281 int MeshShape::RayIntersect (const Vector3& ray_origin,const Vector3& ray_dir,float* pfHitDist) {
00282 if (mpMesh.isNull()) return -1;
00283
00284
00285
00286
00287 Vector3 vMid = 0.5*(mvMin + mvMax);
00288 float fRad = mymax((mvMin-vMid).length(),(mvMax-vMid).length());
00289
00290
00291 if (!Ogre::Ray(ray_origin,ray_dir).intersects(Ogre::Sphere(vMid,fRad + 0.1)).first) return -1;
00292
00293
00294
00295
00296 int iFaceHit = -1;
00297 float myHitDist;
00298
00299
00300
00301 for (int i=0;i<mlIndices.size();i+=3) {
00302 if (IntersectRayTriangle(ray_origin,ray_dir,
00303 mlVertices[mlIndices[i+0]],
00304 mlVertices[mlIndices[i+1]],
00305 mlVertices[mlIndices[i+2]],&myHitDist)) {
00306 if (iFaceHit == -1 || myHitDist < *pfHitDist) { *pfHitDist = myHitDist; iFaceHit = i/3; }
00307 }
00308 }
00309
00310 return iFaceHit;
00311 }
00312
00313 };