//----------------------------------------------------------------------------- // Torque Game Engine // Copyright (C) GarageGames.com, Inc. //----------------------------------------------------------------------------- #include "ts/tsSortedMesh.h" #include "dgl/dgl.h" #include "math/mMath.h" #include "ts/tsShapeInstance.h" // Not worth the effort, much less the effort to comment, but if the draw types // are consecutive use addition rather than a table to go from index to command value... #if ((GL_TRIANGLES+1==GL_TRIANGLE_STRIP) && (GL_TRIANGLE_STRIP+1==GL_TRIANGLE_FAN)) #define getDrawType(a) (GL_TRIANGLES+(a)) #else U32 drawTypes[] = { GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN }; #define getDrawType(a) (drawTypes[a]) #endif // found in tsmesh extern void forceFaceCamera(); extern void forceFaceCameraZAxis(); //----------------------------------------------------- // TSSortedMesh render methods //----------------------------------------------------- void TSSortedMesh::render(S32 frame, S32 matFrame, TSMaterialList * materials) { if (getFlags(Billboard)) { if (getFlags(BillboardZAxis)) forceFaceCameraZAxis(); else forceFaceCamera(); } MatrixF toCam; dglGetModelview(&toCam); toCam.inverse(); Point3F cameraCenter; toCam.getColumn(3,&cameraCenter); S32 firstVert = firstVerts[frame]; S32 vertCount = numVerts[frame]; // note on the following: a TSSortedMesh can animate frame or matFrame but not both. // The reason for this is simple: the number of verts change depending on frame, so // if both varied then there would have to be a new set of tverts for every (frame x matFrame) // combination, rather than for every matFrame as for other mesh types. However, either frame // or matFrame is allowed to vary, accounting for the following odd looking statement. S32 firstTVert = firstTVerts[matFrame ? matFrame : frame]; // set up vertex arrays -- already enabled in TSShapeInstance::render glVertexPointer(3,GL_FLOAT,0,&verts[firstVert]); glNormalPointer(GL_FLOAT,0,getNormals(firstVert)); glTexCoordPointer(2,GL_FLOAT,0,&tverts[firstTVert]); if (TSShapeInstance::smRenderData.detailMapMethod == TSShapeInstance::DETAIL_MAP_MULTI_1 || TSShapeInstance::smRenderData.detailMapMethod == TSShapeInstance::DETAIL_MAP_MULTI_2) { glClientActiveTextureARB(GL_TEXTURE0_ARB + TSShapeInstance::smRenderData.detailMapTE); glTexCoordPointer(2,GL_FLOAT,0,&tverts[firstTVert]); glClientActiveTextureARB(GL_TEXTURE0_ARB + TSShapeInstance::smRenderData.baseTE); } // lock... bool lockArrays = dglDoesSupportCompiledVertexArray(); if (lockArrays) glLockArraysEXT(0,vertCount); if (alwaysWriteDepth) glDepthMask(GL_TRUE); Cluster * cluster; S32 nextCluster = startCluster[frame]; do { // the cluster... cluster = &clusters[nextCluster]; // render the cluster... for (S32 i=cluster->startPrimitive; iendPrimitive; i++) { TSDrawPrimitive & draw = primitives[i]; AssertFatal((draw.matIndex & TSDrawPrimitive::Indexed)!=0,"TSSortedMesh::render: rendering of non-indexed meshes no longer supported"); // material change? if ( (TSShapeInstance::smRenderData.materialIndex ^ draw.matIndex) & (TSDrawPrimitive::MaterialMask|TSDrawPrimitive::NoMaterial)) { setMaterial(draw.matIndex,materials); if (alwaysWriteDepth) glDepthMask(GL_TRUE); } S32 drawType = getDrawType(draw.matIndex>>30); glDrawElements(drawType,draw.numElements,GL_UNSIGNED_SHORT,&indices[draw.start]); } // determine next cluster... if (cluster->frontCluster!=cluster->backCluster) nextCluster = (mDot(cluster->normal,cameraCenter) > cluster->k) ? cluster->frontCluster : cluster->backCluster; else nextCluster = cluster->frontCluster; } while (nextCluster>=0); // unlock... if (lockArrays) glUnlockArraysEXT(); if ((TSShapeInstance::smRenderData.materialFlags & TSMaterialList::Translucent) && alwaysWriteDepth) glDepthMask(GL_FALSE); } void TSSortedMesh::renderFog(S32 frame) { if (getFlags(Billboard)) { if (getFlags(BillboardZAxis)) forceFaceCameraZAxis(); else forceFaceCamera(); } MatrixF toCam; dglGetModelview(&toCam); toCam.inverse(); Point3F cameraCenter; toCam.getColumn(3,&cameraCenter); S32 firstVert = firstVerts[frame]; S32 vertCount = numVerts[frame]; // set up vertex arrays -- already enabled in TSShapeInstance::render glVertexPointer(3,GL_FLOAT,0,&verts[firstVert]); // lock... bool lockArrays = dglDoesSupportCompiledVertexArray(); if (lockArrays) glLockArraysEXT(0,vertCount); Cluster * cluster; S32 nextCluster = startCluster[frame]; do { // the cluster... cluster = &clusters[nextCluster]; // render the cluster... for (S32 i=cluster->startPrimitive; iendPrimitive; i++) { TSDrawPrimitive & draw = primitives[i]; glDrawElements(getDrawType(draw.matIndex>>30),draw.numElements,GL_UNSIGNED_SHORT,&indices[draw.start]); } // determine next cluster... if (cluster->frontCluster!=cluster->backCluster) nextCluster = (mDot(cluster->normal,cameraCenter) > cluster->k) ? cluster->frontCluster : cluster->backCluster; else nextCluster = cluster->frontCluster; } while (nextCluster>=0); // unlock... if (lockArrays) glUnlockArraysEXT(); } //----------------------------------------------------- // TSSortedMesh collision methods //----------------------------------------------------- bool TSSortedMesh::buildPolyList(S32 frame, AbstractPolyList * polyList, U32 & surfaceKey) { frame, polyList, surfaceKey; return false; } bool TSSortedMesh::castRay(S32 frame, const Point3F & start, const Point3F & end, RayInfo * rayInfo) { frame, start, end, rayInfo; return false; } bool TSSortedMesh::buildConvexHull() { return false; } S32 TSSortedMesh::getNumPolys() { S32 count = 0; S32 cIdx = !clusters.size() ? -1 : 0; while (cIdx>=0) { Cluster & cluster = clusters[cIdx]; for (S32 i=cluster.startPrimitive; i