📄 cvshapes.cpp
字号:
// Set up an array to remember where each point of each face came from
int *pSource = new int[face_data_size]; // very conservative
int iSource = 0; // running index
// Set up a table that goes coord num => face num
int *pCoordToFace = new int[pNode->coordIndex.num];
// j is first index into coordIndex for each face
for(j = 0; j< pNode->coordIndex.num; j++, iface++)
{
// do a face
int nVerts = VertCount(pNode->coordIndex, j); // # verts in -this face-
GxVec3f n;
// note that the sense of normals depend upon ccw or cw
// if the norms point in to the front surface no shading will be done
// on -either side-
// Notice the back norm, if kept, is right after the front norm
if(pNormals->IsPerFace())
{
pNormals->GetFaceNormal( iface, n );
if(faceNorms[iface] == -1)
{
n = -n;
faceNorms[iface] = numN;
if(boolBackCull && boolCCW) n = -n;
#if (defined(FLIP_D3D_NORMALS) && defined(CH_USE_D3D))
n = -n;
#endif
pN[numN++] = n;
if(!boolBackCull) pN[numN++] = -n;
}
}
for(int k = 0; k < nVerts; k++)
{
pCoordToFace[j+k] = iface; // Build table for later
}
bool boolConvex = IsConvex( j, nVerts );
int iNumFacets = 1; // How many individual convex facets in this face
ChTriangulator tri;
//boolConvex = true; // VSP : temporary fix for this release
if(!boolConvex)
{
#if 1
if(tri.Attach(pNode->coordIndex.values + j, (GxVec3f*)(pC3->point.values), nVerts))
{
iNumFacets = tri.GetCount();
}
else
{
boolConvex = true; // triangulation failed. Proceed as if convex
}
#endif
}
for( int iFacet = 0; iFacet < iNumFacets; iFacet++)
{
int nVertsFacet = boolConvex ? nVerts : 3;
face_data[ifd] = nVertsFacet;
if(!boolBackCull) face_data[ifd+2*nVertsFacet+1] = nVertsFacet;
ifd++;
int triIndex[3];
if(!boolConvex)
{
tri.GetTriangle(iFacet, triIndex);
}
for(int k = 0; k < nVertsFacet; k++)
{
int normIndex;
int vertIndex;
int iVertNumber;
if(boolConvex)
{
iVertNumber = j + k;
}
else
{
iVertNumber = j + triIndex[k];
}
int index = pNode->coordIndex.values[iVertNumber];
// First, add a vert to the vert array, and remember where in pV it is
// To save even more space, we could build a tree where the key is index + texIndex
// But that would be slower, probably.
if(boolUseTexture)
{
int texIndex = pTxMap->GetIndex(iVertNumber);
vertIndex = -1;
if(verts[index] == -1)
{
// Store the first occurrence of a unique vertex into pV, and save where
// pV will store all the -used- vertices from the C3 node
// Also save the tex index, so we can see on later verts if their
// tex coords match. If so, we'll be able to reuse this vertex.
// This enforces the rule: Different tex coords ==> different verts
int iC3 = index * 3;
GxVec3f p;
p.x() = pC3->point.values[iC3];
p.y() = pC3->point.values[iC3+1];
p.z() = pC3->point.values[iC3+2];
verts[index] = numV;
vertIndex = numV;
pV[numV++] = p;
texIndices[index] = texIndex;
}
else if(texIndices[index] == texIndex)
{
vertIndex = verts[index]; // tex coords match, use the shared array
}
else
{
int iC3 = index * 3; // Use the unshared array
GxVec3f p;
p.x() = pC3->point.values[iC3];
p.y() = pC3->point.values[iC3+1];
p.z() = pC3->point.values[iC3+2];
texVerts[iVertNumber] = numV;
vertIndex = numV;
pV[numV++] = p;
}
}
else
{
if(verts[index] == -1)
{
// Store the first occurrence of a unique vertex into pV, and save where
// pV will store all the -used- vertices from the C3 node
int iC3 = index * 3;
GxVec3f p;
p.x() = pC3->point.values[iC3];
p.y() = pC3->point.values[iC3+1];
p.z() = pC3->point.values[iC3+2];
verts[index] = numV;
vertIndex = numV;
pV[numV++] = p;
}
else
{
vertIndex = verts[index];
}
}
// Get the normal, if it's by vertex or default ....
// We store it in one of three arrays, and remember its index
// in the pN array
if(pNormals->IsPerFace())
{
normIndex = faceNorms[iface];
}
else if(pNormals->IsPerVertex())
{
// This could be better if we saved
// by normal index instead of vertNumber
pNormals->GetVertexNormal( iVertNumber, n );
n = -n;
if(uniqueNorms[iVertNumber] == -1)
{
uniqueNorms[iVertNumber] = numN;
// n.z() = -n.z();
if(boolBackCull && boolCCW) n = -n;
#if (defined(FLIP_D3D_NORMALS) && defined(CH_USE_D3D))
n = -n;
#endif
pN[numN++] = n;
if(!boolBackCull) pN[numN++] = -n;
}
normIndex = uniqueNorms[iVertNumber];
}
else
{
chuint32 normFlag;
pNormals->GetDefaultNormal( iVertNumber, iface, n, normFlag );
n = -n;
#if (defined(FLIP_D3D_NORMALS) && defined(CH_USE_D3D))
n = -n;
#endif
if(normFlag & GX_NORMAL_FACE)
{
if(faceNorms[iface] == -1)
{
faceNorms[iface] = numN;
if(boolBackCull && boolCCW) n = -n;
pN[numN++] = n;
if(!boolBackCull) pN[numN++] = -n;
}
normIndex = faceNorms[iface];
}
else if(normFlag & GX_NORMAL_ALL_FACES)
{
if(sharedNorms[index] == -1)
{
sharedNorms[index] = numN;
if(boolBackCull && boolCCW) n = -n;
#if (defined(FLIP_D3D_NORMALS) && defined(CH_USE_D3D))
n = -n;
#endif
pN[numN++] = n;
if(!boolBackCull) pN[numN++] = -n;
}
normIndex = sharedNorms[index];
}
else
{
if(uniqueNorms[iVertNumber] == -1)
{
uniqueNorms[iVertNumber] = numN;
if(boolBackCull && boolCCW) n = -n;
#if (defined(FLIP_D3D_NORMALS) && defined(CH_USE_D3D))
n = -n;
#endif
pN[numN++] = n;
if(!boolBackCull) pN[numN++] = -n;
}
normIndex = uniqueNorms[iVertNumber];
}
}
// Whew, now we have indices for both vert and norm, so add them to
// the face_data
int bump = 0;
if(!boolBackCull || !boolCCW)
{
face_data[ifd+k*2] = vertIndex;
face_data[ifd+k*2+1] = normIndex++;
bump = 2 * nVertsFacet + 1;
pSource[iSource+k] = iVertNumber;
}
// Add backface index
if(!boolBackCull || boolCCW)
{
int reverseIndex = ifd + 2 * nVertsFacet - 2 * k - 2 + bump;
face_data[reverseIndex] = vertIndex;
face_data[reverseIndex + 1] = normIndex;
pSource[iSource + nVertsFacet - k - 1 + (bump?nVertsFacet:0)] = iVertNumber;
}
}
ifd += nVertsFacet * 2;
iSource += nVertsFacet;
if (!boolBackCull)
{
ifd += nVertsFacet * 2 + 1;
iSource += nVertsFacet;
}
}
j += nVerts; // next face -- the j++ in loop bumps over -1
}
face_data[ifd] = 0;
// Load the verts and faces
ChNrFaceArray facesAdded;
int numFacesAdded;
ChNrMeshAddFaces(mesh,
numV,
(ChNrVector*) pV,
numN,
(ChNrVector*) pN,
face_data,
&numFacesAdded,
&facesAdded);
// Assign colors and textures to faces
int inc = 1;
if(!boolBackCull) inc *= 2; // only every other face if we did back faces
unsigned int ifacet;
#if defined(CH_USE_D3D)
numFacesAdded = facesAdded->GetSize();
#endif
for( ifacet = 0, j = 0; int(ifacet) < numFacesAdded; ifacet += inc)
{
ChNrFace elt;
int count = ChNrFaceGetVertexCount(GetElement(facesAdded, ifacet, elt));
D3DRelease(elt);
for(int k = 0; k < count; k++)
{
iSource = j * inc + k;
if(boolCCW && boolBackCull)
{
// reverse the texture && material coords; we already reversed the vertex order
//iSource = j + count - k - 1;
}
int iVertNumber = pSource[iSource];
int iface = pCoordToFace[iVertNumber];
int index = ChNrFaceGetVertexIndex(GetElement(facesAdded,ifacet, elt), k);
D3DRelease(elt);
if(boolUseTexture)
{
int iC3 = pNode->coordIndex.values[iVertNumber] * 3;
GxVec3f textCoord = pTxMap->GetCoord3(iVertNumber, pC3->point.values+iC3);
ChNrMeshSetTextureCoordinates(mesh, index, textCoord.x(), textCoord.y());
}
if(k == 0 || !boolColorByFace)
{
// Color the verts if necessary, but just faces if possible
int iVert = boolColorByFace ? -1 : index; // -1 means set face color
materialMap.Set(mesh, GetElement(facesAdded, unsigned(ifacet), elt), iVert, iface, iVertNumber);
D3DRelease(elt);
}
}
// If we applied a color to the face for some reason (like transparency)
// we need to copy that color to the backface, if there is one
// BUG HERE! We are not handling meshes with a mixture of transparency
// and opaque
if( inc > 1 /*!boolBackCull && (ChNrMeshGetColorSource(mesh) == ColorFromFace )*/)
{
ChNrFace elt;
ChNativeColor color = ChNrFaceGetColor(GetElement(facesAdded, ifacet, elt));
D3DRelease(elt);
ChNrFaceSetColor(GetElement(facesAdded, ifacet+1, elt), color);
D3DRelease(elt);
}
j += count;
}
m_boolCanCollapse = (ChNrMeshGetColorSource(mesh) == ColorFromFace );
//ChNrFrameSetColor(m_frame, RLCreateColorRGBA(RLVal(0.6), RLVal(0.6), RLVal(0.6),
// RLVal(0.4)));
if(boolUseTexture)
{
// This is in case the texture is already arrived
ChTextureHandle hdl = pTextureData->GetTextureHandle();
if(hdl)
{
// Texture guy got here first, apply it
//ChNrMeshSetTexture(mesh, hdl);
SetTexture(pTextureData);
}
}
// Cleanup
delete [] pN;
delete [] pV;
delete [] faceNorms;
delete [] uniqueNorms;
delete [] sharedNorms;
delete [] verts;
delete [] face_data;
delete [] texIndices;
delete [] texVerts;
delete [] pSource;
delete [] pCoordToFace;
ChNrFree(facesAdded);
delete pTxMap;
}
else
{
// Notify them of the bad node TODO
}
pIterator->DidAShape();
pRC->UnlockQv();
pRC->UnlockScene();
}
#endif
return true;
}
bool ChQvIFSInstance::Draw(ChRenderContext *pRC, ChDrawIterator *pIterator)
{
#if defined( CH_USE_3DR )
{
G3dHandle_t hGC = pRC->GetGC();
Dword_t hRC = pRC->GetRC();
QvIndexedFaceSet *pNode = (QvIndexedFaceSet *)GetNode();
pRC->SetModelTransform(GetTransform());
pRC->SetShading(this);
Fixed32_t wMattNum = 0; // for now always use material 0
G3dSetCurrentMatt(hGC, wMattNum );
// Interpret shapehints; we assume there is at least one there; (we inited to make sure)
Fixed32_t lIsCCW = (GetShapeHints()->vertexOrdering.value == QvShapeHints::COUNTERCLOCKWISE);
G3dSetState( hGC, G3DL_FRONT_CCW, &lIsCCW);
// Figure out if we can backcull. solid + known order means we can
bool boolBackCull = ((GetShapeHints()->vertexOrdering.value != QvShapeHints::UNKNOWN_ORDERING) &&
(GetShapeHints()->shapeType.value == QvShapeHints::SOLID));
Float_t cull = boolBackCull;
G3dSetMatt( hGC, wMattNum, G3DM_BACK_CULL, (Float_t *)&cull );
// Make a material mapping; we will use later for each face
ChQvFaceSetMaterials materialMap( this ); // making this is cheap; don't cache
// Normals
int face = 0;
/* If they can't write good nodes, don't draw them! */
if(((ChQvIFSRenderData *)m_pRenderData)->IsValid())
{
ChQvIndexedFaceSetNormals *pNormals = ((ChQvIFSRenderData *)m_pRenderData)->GetNormals();
/* Do the texture stuff - find it, make the map, set up 3dr for it, */
int boolUseTexture = false;
ChQvTextureRenderData *pTextureData = 0;
pTextureData = (ChQvTextureRenderData*)(GetTexture2()->GetRenderData());
if (pTextureData->GetTextureHandle()) boolUseTexture = true;
ChQvIFSTextures *pTxMap = 0;
if(boolUseTexture)
{
pRC->SetTexture(pTextureData->GetTextureHandle());
pTxMap = new ChQvIFSTextures( this ); // efficient except for many-faced
// textured ifs' with default map,
// which are unlikely because they
// would be b ugly, so don't
// bother to
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -