📄 tsmesh.cc
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "ts/tsMesh.h"
#include "dgl/dgl.h"
#include "math/mMath.h"
#include "math/mathIO.h"
#include "ts/tsShape.h"
#include "console/console.h"
#include "ts/tsShapeInstance.h"
#include "sim/sceneObject.h"
#include "ts/tsSortedMesh.h"
#include "core/bitRender.h"
#include "collision/convex.h"
#include "core/frameAllocator.h"
#include "platform/profiler.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
// structures used to share data between detail levels...
// used (and valid) during load only
Vector<Point3F*> TSMesh::smVertsList;
Vector<Point3F*> TSMesh::smNormsList;
Vector<U8*> TSMesh::smEncodedNormsList;
Vector<Point2F*> TSMesh::smTVertsList;
Vector<bool> TSMesh::smDataCopied;
Vector<Point3F> TSMesh::smSaveVerts;
Vector<Point3F> TSMesh::smSaveNorms;
Vector<Point2F> TSMesh::smSaveTVerts;
Vector<MatrixF*> TSSkinMesh::smInitTransformList;
Vector<S32*> TSSkinMesh::smVertexIndexList;
Vector<S32*> TSSkinMesh::smBoneIndexList;
Vector<F32*> TSSkinMesh::smWeightList;
Vector<S32*> TSSkinMesh::smNodeIndexList;
Vector<Point3F> gNormalStore;
F32 TSMesh::overrideFadeVal = 1.0;
bool TSMesh::smUseTriangles = false; // convert all primitives to triangle lists on load
bool TSMesh::smUseOneStrip = false; // join triangle strips into one long strip on load
S32 TSMesh::smMinStripSize = 1; // smallest number of _faces_ allowed per strip (all else put in tri list)
bool TSMesh::smUseEncodedNormals = false;
// quick function to force object to face camera -- currently throws out roll :(
void forceFaceCamera()
{
MatrixF mat;
Point4F p;
dglGetModelview(&mat);
mat.getColumn(3,&p);
mat.identity();
mat.setColumn(3,p);
dglLoadMatrix(&mat);
if (TSShapeInstance::smRenderData.objectScale)
glScalef(TSShapeInstance::smRenderData.objectScale->x,
TSShapeInstance::smRenderData.objectScale->y,
TSShapeInstance::smRenderData.objectScale->z);
}
void forceFaceCameraZAxis()
{
MatrixF mat;
dglGetModelview(&mat);
Point3F z;
mat.getColumn(2,&z); // this is where the z-axis goes, keep it here but reset x and y
Point3F x,y;
if (mFabs(z.y) < 0.99f)
{
// mCross(Point3F(0,1,0),tAxis,&x);
x.set(z.z,0,-z.x);
x.normalize();
mCross(z,x,&y);
}
else
{
// mCross(z,Point3F(1,0,0),&y);
y.set(0,z.z,-z.y);
y.normalize();
mCross(y,z,&x);
}
mat.setColumn(0,x);
mat.setColumn(1,y);
mat.setColumn(2,z);
dglLoadMatrix(&mat);
if (TSShapeInstance::smRenderData.objectScale)
glScalef(TSShapeInstance::smRenderData.objectScale->x,TSShapeInstance::smRenderData.objectScale->y,TSShapeInstance::smRenderData.objectScale->z);
}
void TSMesh::saveMergeVerts()
{
S32 startMerge = vertsPerFrame - mergeIndices.size();
S32 j;
for (j=0; j<mergeIndices.size(); j++)
{
smSaveVerts[j+mergeBufferStart] = verts[j+startMerge];
smSaveTVerts[j+mergeBufferStart] = tverts[j+startMerge];
}
F32 mult = TSShapeInstance::smRenderData.intraDetailLevel;
for (j=0; j<mergeIndices.size(); j++)
{
verts[j+startMerge] *= mult;
Point3F v = mergeIndices[j]<startMerge ? verts[mergeIndices[j]] : smSaveVerts[mergeIndices[j]-startMerge+mergeBufferStart];
v *= 1.0f - mult;
verts[j+startMerge] += v;
tverts[j+startMerge] *= mult;
Point2F tv = mergeIndices[j]<startMerge ? tverts[mergeIndices[j]] : smSaveTVerts[mergeIndices[j]-startMerge+mergeBufferStart];
tv *= 1.0f - mult;
tverts[j+startMerge] += tv;
}
}
void TSMesh::restoreMergeVerts()
{
S32 startMerge = vertsPerFrame - mergeIndices.size();
for (S32 i=0; i<mergeIndices.size(); i++)
{
verts[i+startMerge] = smSaveVerts[i+mergeBufferStart];
tverts[i+startMerge] = smSaveTVerts[i+mergeBufferStart];
}
}
void TSMesh::saveMergeNormals()
{
S32 startMerge = vertsPerFrame - mergeIndices.size();
S32 j;
smSaveNorms.setSize(mergeIndices.size());
for (j=0; j<mergeIndices.size(); j++)
smSaveNorms[j] = norms[j+startMerge];
F32 mult = TSShapeInstance::smRenderData.intraDetailLevel;
for (j=0; j<mergeIndices.size(); j++)
{
norms[j+startMerge] *= mult;
Point3F n = mergeIndices[j]<startMerge ? norms[mergeIndices[j]] : smSaveNorms[mergeIndices[j]-startMerge];
n *= 1.0f - mult;
norms[j+startMerge] += n;
// norms[j+startMerge].normalize();
}
}
void TSMesh::restoreMergeNormals()
{
if (getFlags(UseEncodedNormals))
return;
S32 startMerge = vertsPerFrame - mergeIndices.size();
for (S32 i=0; i<mergeIndices.size(); i++)
norms[i+startMerge] = smSaveNorms[i];
}
//-----------------------------------------------------
// TSMesh render methods
//-----------------------------------------------------
void TSMesh::fillVB(S32 vb, S32 frame, S32 matFrame, TSMaterialList *materials)
{
S32 firstVert = vertsPerFrame * frame;
S32 firstTVert = vertsPerFrame * matFrame;
const Point3F *normals = getNormals(firstVert);
// set up vertex arrays -- already enabled in TSShapeInstance::render
glVertexPointer(3,GL_FLOAT,0,&verts[firstVert]);
glNormalPointer(GL_FLOAT,0,normals);
glTexCoordPointer(2,GL_FLOAT,0,&tverts[firstTVert]);
TSDrawPrimitive &draw = primitives[0];
AssertFatal(draw.matIndex & TSDrawPrimitive::Indexed,
"TSMesh::render: rendering of non-indexed meshes no longer supported");
// we do this to enable texturing -- if necessary
if (((TSShapeInstance::smRenderData.materialIndex ^ draw.matIndex) &
(TSDrawPrimitive::MaterialMask|TSDrawPrimitive::NoMaterial)) != 0)
setMaterial(draw.matIndex,materials);
glFillVertexBufferEXT(vb,0,vertsPerFrame);
}
void TSMesh::morphVB(S32 vb, S32 morph, S32 frame, S32 matFrame, TSMaterialList *materials)
{
S32 firstVert = vertsPerFrame * (frame+1) - morph;
S32 firstTVert = vertsPerFrame * (matFrame+1) - morph;
const Point3F *normals = getNormals(firstVert);
saveMergeNormals(); // verts & tverts saved and restored on tsshapeinstance::setStatics
// set up vertex arrays -- already enabled in TSShapeInstance::render
glVertexPointer(3,GL_FLOAT,0,&verts[firstVert]);
glNormalPointer(GL_FLOAT,0,normals);
glTexCoordPointer(2,GL_FLOAT,0,&tverts[firstTVert]);
TSDrawPrimitive &draw = primitives[0];
AssertFatal(draw.matIndex & TSDrawPrimitive::Indexed,
"TSMesh::render: rendering of non-indexed meshes no longer supported");
// we do this to enable texturing -- if necessary
if (((TSShapeInstance::smRenderData.materialIndex ^ draw.matIndex) &
(TSDrawPrimitive::MaterialMask|TSDrawPrimitive::NoMaterial)) != 0)
setMaterial(draw.matIndex,materials);
glFillVertexBufferEXT(vb,0,morph);
restoreMergeNormals();
}
void TSMesh::renderVB(S32 frame, S32 matFrame, TSMaterialList *materials)
{
S32 firstVert = vertsPerFrame * frame;
S32 firstTVert = vertsPerFrame * matFrame;
if (getFlags(Billboard))
{
if (getFlags(BillboardZAxis))
forceFaceCameraZAxis();
else
forceFaceCamera();
}
const Point3F *normals = getNormals(firstVert);
// lock...
bool lockArrays = dglDoesSupportCompiledVertexArray();
if (lockArrays)
glLockArraysEXT(0,vertsPerFrame);
for (S32 i=0; i<primitives.size(); i++)
{
PROFILE_START(TSShapeInstanceVBMat);
TSDrawPrimitive &draw = primitives[i];
AssertFatal(draw.matIndex & TSDrawPrimitive::Indexed,
"TSMesh::render: rendering of non-indexed meshes no longer supported");
// material change?
if (((TSShapeInstance::smRenderData.materialIndex ^ draw.matIndex) &
(TSDrawPrimitive::MaterialMask|TSDrawPrimitive::NoMaterial)) != 0)
setMaterial(draw.matIndex,materials);
PROFILE_END();
PROFILE_START(TSShapeInstanceDE);
S32 drawType = getDrawType(draw.matIndex>>30);
glDrawElements(drawType,draw.numElements,GL_UNSIGNED_SHORT,&indices[draw.start]);
PROFILE_END();
}
// unlock...
if (lockArrays)
glUnlockArraysEXT();
}
void TSMesh::render(S32 frame, S32 matFrame, TSMaterialList * materials)
{
if( vertsPerFrame <= 0 ) {
return;
}
S32 firstVert = vertsPerFrame * frame;
S32 firstTVert = vertsPerFrame * matFrame;
if (getFlags(Billboard))
{
if (getFlags(BillboardZAxis))
forceFaceCameraZAxis();
else
forceFaceCamera();
}
const Point3F * normals = getNormals(firstVert);
saveMergeNormals(); // verts & tverts saved and restored on tsshapeinstance::setStatics
// set up vertex arrays -- already enabled in TSShapeInstance::render
glVertexPointer(3,GL_FLOAT,0,&verts[firstVert]);
glNormalPointer(GL_FLOAT,0,normals);
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,vertsPerFrame);
for (S32 i=0; i<primitives.size(); i++)
{
TSDrawPrimitive & draw = primitives[i];
AssertFatal(draw.matIndex & TSDrawPrimitive::Indexed,
"TSMesh::render: rendering of non-indexed meshes no longer supported");
// material change?
if ( ((TSShapeInstance::smRenderData.materialIndex ^ draw.matIndex) &
(TSDrawPrimitive::MaterialMask|TSDrawPrimitive::NoMaterial)) != 0)
setMaterial(draw.matIndex,materials);
S32 drawType = getDrawType(draw.matIndex>>30);
glDrawElements(drawType,draw.numElements,GL_UNSIGNED_SHORT,&indices[draw.start]);
}
// unlock...
if (lockArrays)
glUnlockArraysEXT();
restoreMergeNormals();
}
const Point3F * TSMesh::getNormals(S32 firstVert)
{
if (getFlags(UseEncodedNormals))
{
gNormalStore.setSize(vertsPerFrame);
for (S32 i=0; i<encodedNorms.size(); i++)
gNormalStore[i]=decodeNormal(encodedNorms[i+firstVert]);
return gNormalStore.address();
}
return &norms[firstVert];
}
void TSMesh::initMaterials()
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -