Mesh* TriObject::GetRenderMesh(TimeValue t, INode *inode, View &view, BOOL& needDelete) { if (mDisableDisplacement || !(view.flags & RENDER_MESH_DISPLACEMENT_MAP)) { needDelete = FALSE; return &mesh; } // need to check the mesh and see if any face has a matId the requires displacment mapping BOOL needDisp = FALSE; // Get the material Mtl* pMtl = inode ? inode->GetMtl() : NULL; if (pMtl) { // does the mesh as a whole need it if (pMtl->Requirements(mesh.mtlIndex)&MTLREQ_DISPLACEMAP) needDisp = TRUE; if (!needDisp) { for (int f = 0; f < mesh.numFaces; f++) { if (pMtl->Requirements(mesh.getFaceMtlIndex(f))&MTLREQ_DISPLACEMAP) { needDisp = TRUE; break; } } } if (needDisp) { if (mesh.getNumFaces() == 0) return &mesh; Matrix3 otm; if (inode) otm = inode->GetObjectTM(t); else otm.IdentityMatrix(); GetGTessFunction(); if (mSubDivideDisplacement && psGTessFunc) { // if we have a material that does displacement mapping and if we can do it Mesh *pMesh = new Mesh(); needDelete = TRUE; (*psGTessFunc)((void *)&mesh, MAX_MESH, &otm, pMesh, NULL, &mDispApprox, &view, pMtl, FALSE, mSplitMesh); needDelete = TRUE; return pMesh; } else { Mesh *pMesh = new Mesh(mesh); needDelete = TRUE; BOOL hasUVs = pMesh->tvFace != NULL; pMesh->buildRenderNormals(); // now displace the verts BitArray vertsSet; vertsSet.SetSize(pMesh->numVerts); for (int f = 0; f < pMesh->numFaces; f++) { Face *pFace = &pMesh->faces[f]; TVFace *pTVFace = &pMesh->tvFace[f]; int matid = pFace->getMatID(); for (int v = 0; v < 3; v++) { int vidx = pFace->v[v]; if (vertsSet[vidx]) continue; // displace only once Point3 norm = pMesh->getNormal(vidx); norm.Normalize(); Point3& vert = pMesh->getVert(vidx); UVVert uvvert; if (hasUVs) uvvert = pMesh->getTVert(pTVFace->t[v]); else { uvvert.x = 0.0; uvvert.y = 0.0; } pMesh->buildBoundingBox(); Box3 bbox = pMesh->getBoundingBox(); float dispScale = Length(bbox.pmax - bbox.pmin)/10.0f; float disp = GetDisp(pMtl, pMesh, f, pFace->getMatID(), vert, uvvert.x, uvvert.y, otm) * dispScale; vert += (norm * disp); vertsSet.Set(vidx); } } return pMesh; } } } needDelete = FALSE; return &mesh; }
void XsiExp::ExportMesh( INode * node, TimeValue t, int indentLevel) { ObjectState os = node->EvalWorldState(t); if (!os.obj || os.obj->SuperClassID() != GEOMOBJECT_CLASS_ID) { return; // Safety net. This shouldn't happen. } BOOL needDel; TriObject * tri = GetTriObjectFromNode(node, t, needDel); if (!tri) { // no tri object return; } // prepare mesh Mesh * mesh = &tri->GetMesh(); mesh->buildNormals(); // object offset matrix; apply to verts // swap y and z; max to soft correction Matrix3 matrix(1); // translate matrix.PreTranslate( Point3( node->GetObjOffsetPos().x, node->GetObjOffsetPos().z, -node->GetObjOffsetPos().y)); // rotate AngAxis aa( node->GetObjOffsetRot()); float temp = aa.axis.z; aa.axis.z = -aa.axis.y; aa.axis.y = temp; PreRotateMatrix(matrix, Quat( aa)); // scale ScaleValue scale = node->GetObjOffsetScale(); aa.Set( scale.q); temp = aa.axis.z; aa.axis.z = -aa.axis.y; aa.axis.y = temp; scale.q.Set( aa); temp = scale.s.z; scale.s.z = scale.s.y; scale.s.y = temp; ApplyScaling(matrix, scale); // apply root transform matrix = matrix * topMatrix; // only rotation for normals AffineParts ap; Matrix3 rotMatrix(1); decomp_affine( matrix, &ap); PreRotateMatrix( rotMatrix, ap.q); // set winding order int vx1 = 0, vx2 = 1, vx3 = 2; if (TMNegParity( node->GetNodeTM(GetStaticFrame())) != TMNegParity( matrix) ) { // negative scaling; invert winding order and normal rotation vx1 = 2; vx2 = 1; vx3 = 0; rotMatrix = rotMatrix * Matrix3( Point3(-1,0,0), Point3(0,-1,0), Point3(0,0,-1), Point3(0,0,0)); } // header TSTR indent = GetIndent(indentLevel+1); fprintf(pStream, "%s%s %s {\n",indent.data(), "Mesh", FixupName(node->GetName())); // write number of verts int numLoop = mesh->getNumVerts(); fprintf(pStream, "%s\t%d;\n",indent.data(), numLoop); // write verts for (int i = 0; i < numLoop; i++) { Point3 v = mesh->verts[i]; float temp = v.z; v.z = -v.y; v.y = temp; v = matrix * v; fprintf(pStream, "%s\t%.6f;%.6f;%.6f;%s\n", indent.data(), v.x, v.y, v.z, i == numLoop - 1 ? ";\n" : ","); } // write number of faces numLoop = mesh->getNumFaces(); fprintf(pStream, "%s\t%d;\n", indent.data(), numLoop); // write faces for (i = 0; i < numLoop; i++) { fprintf(pStream, "%s\t3;%d,%d,%d;%s\n", indent.data(), mesh->faces[i].v[vx1], mesh->faces[i].v[vx2], mesh->faces[i].v[vx3], i == numLoop - 1 ? ";\n" : ","); } // face materials Mtl * nodeMtl = node->GetMtl(); int numMtls = !nodeMtl || !nodeMtl->NumSubMtls() ? 1 : nodeMtl->NumSubMtls(); // write face material list header fprintf(pStream, "%s\tMeshMaterialList {\n", indent.data()); // write number of materials fprintf(pStream, "%s\t\t%d;\n", indent.data(), numMtls); // write number of faces fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop); // write face material indices (1 for each face) for (i = 0; i < numLoop; i++) { int index = numMtls ? mesh->faces[i].getMatID() % numMtls : 0; fprintf(pStream,"%s\t\t%d%s\n", indent.data(), index, i == numLoop - 1 ? ";\n" : ","); } // write the materials ExportMaterial( node, indentLevel+2); // verts close brace fprintf(pStream, "%s\t}\n\n",indent.data()); // write normals header fprintf(pStream, "%s\t%s {\n", indent.data(), "SI_MeshNormals"); // write number of normals fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop * 3); // write normals (3 for each face) for (i = 0; i < numLoop; i++) { Face * f = &mesh->faces[i]; int vert = f->getVert(vx1); Point3 vn = GetVertexNormal(mesh, i, mesh->getRVertPtr(vert)); float temp = vn.z; vn.z = -vn.y; vn.y = temp; vn = rotMatrix * vn; fprintf(pStream,"%s\t\t%.6f;%.6f;%.6f;,\n", indent.data(), vn.x, vn.y, vn.z); vert = f->getVert(vx2); vn = GetVertexNormal(mesh, i, mesh->getRVertPtr(vert)); temp = vn.z; vn.z = -vn.y; vn.y = temp; vn = rotMatrix * vn; fprintf(pStream,"%s\t\t%.6f;%.6f;%.6f;,\n", indent.data(), vn.x, vn.y, vn.z); vert = f->getVert(vx3); vn = GetVertexNormal(mesh, i, mesh->getRVertPtr(vert)); temp = vn.z; vn.z = -vn.y; vn.y = temp; vn = rotMatrix * vn; fprintf(pStream,"%s\t\t%.6f;%.6f;%.6f;%s\n", indent.data(), vn.x, vn.y, vn.z, i == numLoop - 1 ? ";\n" : ","); } // write number of faces fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop); // write faces for (i = 0; i < numLoop; i++) { fprintf(pStream, "%s\t\t%d;3;%d,%d,%d;%s\n", indent.data(), i, i * 3 + vx1, i * 3 + vx2, i * 3 + vx3, i == numLoop - 1 ? ";\n" : ","); } // normals close brace fprintf(pStream, "%s\t}\n\n",indent.data()); // texcoords if (nodeMtl && mesh && (nodeMtl->Requirements(-1) & MTLREQ_FACEMAP)) { // facemapping numLoop = mesh->getNumFaces() * 3; // write texture coords header fprintf(pStream, "%s\tSI_MeshTextureCoords {\n", indent.data()); // write number of texture coords fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop); // write texture coords for (int i = 0; i < numLoop; i++) { Point3 tv[3]; Face * f = &mesh->faces[i]; make_face_uv( f, tv); fprintf(pStream, "%s\t\t%.6f;%.6f;,\n", indent.data(), tv[0].x, tv[0].y); fprintf(pStream, "%s\t\t%.6f;%.6f;,\n", indent.data(), tv[1].x, tv[1].y); fprintf(pStream, "%s\t\t%.6f;%.6f;%s\n", indent.data(), tv[2].x, tv[2].y, i == numLoop - 1 ? ";\n" : ","); } // write number of faces numLoop = mesh->getNumFaces(); fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop); // write faces for (i = 0; i < numLoop; i++) { fprintf(pStream,"%s\t\t%d;3;%d,%d,%d;%s\n", indent.data(), i, mesh->tvFace[i].t[vx1], mesh->tvFace[i].t[vx2], mesh->tvFace[i].t[vx3], i == numLoop - 1 ? ";\n" : ","); } // texture coords close brace fprintf(pStream, "%s\t}\n\n", indent.data()); } else { numLoop = mesh->getNumTVerts(); if (numLoop) { // write texture coords header fprintf(pStream, "%s\tSI_MeshTextureCoords {\n", indent.data()); // write number of texture coords fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop); // write texture coords for (i = 0; i < numLoop; i++) { UVVert tv = mesh->tVerts[i]; fprintf(pStream, "%s\t\t%.6f;%.6f;%s\n", indent.data(), tv.x, tv.y, i == numLoop - 1 ? ";\n" : ","); } // write number of faces numLoop = mesh->getNumFaces(); fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop); // write faces for (i = 0; i < numLoop; i++) { fprintf(pStream,"%s\t\t%d;3;%d,%d,%d;%s\n", indent.data(), i, mesh->tvFace[i].t[vx1], mesh->tvFace[i].t[vx2], mesh->tvFace[i].t[vx3], i == numLoop - 1 ? ";\n" : ","); } // texture coords close brace fprintf(pStream, "%s\t}\n\n", indent.data()); } } /* // Export color per vertex info if (GetIncludeVertexColors()) { int numCVx = mesh->numCVerts; fprintf(pStream, "%s\t%s %d\n",indent.data(), ID_MESH_NUMCVERTEX, numCVx); if (numCVx) { fprintf(pStream,"%s\t%s {\n",indent.data(), ID_MESH_CVERTLIST); for (i=0; i<numCVx; i++) { Point3 vc = mesh->vertCol[i]; fprintf(pStream, "%s\t\t%s %d\t%s\n",indent.data(), ID_MESH_VERTCOL, i, Format(vc)); } fprintf(pStream,"%s\t}\n",indent.data()); fprintf(pStream, "%s\t%s %d\n",indent.data(), ID_MESH_NUMCVFACES, mesh->getNumFaces()); fprintf(pStream, "%s\t%s {\n",indent.data(), ID_MESH_CFACELIST); for (i=0; i<mesh->getNumFaces(); i++) { fprintf(pStream,"%s\t\t%s %d\t%d\t%d\t%d\n", indent.data(), ID_MESH_CFACE, i, mesh->vcFace[i].t[vx1], mesh->vcFace[i].t[vx2], mesh->vcFace[i].t[vx3]); } fprintf(pStream, "%s\t}\n",indent.data()); } } */ // Mesh close brace fprintf(pStream, "%s}\n",indent.data()); // dispose of tri object if (needDel) { delete tri; } }
void MeshExporter::_dumpMaterial(Rad::Material * m, IGameMaterial * mtl) { Point4 val4; Point3 val3; PropType pt; IGameProperty* p = NULL; p = mtl->GetAmbientData(); if (p) { pt = p->GetType(); if (pt == IGAME_POINT3_PROP && p->GetPropertyValue(val3)) { m->ambient = Float3(val3.x, val3.y, val3.z); } } p = mtl->GetDiffuseData(); if (p) { pt = p->GetType(); if (pt == IGAME_POINT3_PROP && p->GetPropertyValue(val3)) { m->diffuse = Float3(val3.x, val3.y, val3.z); } } p = mtl->GetSpecularData(); if (p) { pt = p->GetType(); if (pt == IGAME_POINT3_PROP && p->GetPropertyValue(val3)) { m->specular = Float3(val3.x, val3.y, val3.z); } } p = mtl->GetSpecularLevelData(); if (p) { float specularPower; if (p->GetPropertyValue(specularPower)) { m->shininess = specularPower; } } p = mtl->GetEmissiveData(); if (p) { pt = p->GetType(); if (pt == IGAME_POINT3_PROP && p->GetPropertyValue(val3)) { m->emissive = Float3(val3.x, val3.y, val3.z); } } Mtl * maxMtl = mtl->GetMaxMaterial(); ULONG flag = maxMtl->Requirements(0); if (flag & MTLREQ_2SIDE) { m->cullMode = eCullMode::NONE; } d_assert (!mtl->IsMultiType()); int numTextures = mtl->GetNumberOfTextureMaps(); for ( int index = 0; index < numTextures; ++index ) { IGameTextureMap * pMap = mtl->GetIGameTextureMap(index); if (!pMap) continue; const int type = pMap->GetStdMapSlot(); const char * tex = pMap->GetBitmapFileName(); const char * ttt = pMap->GetTextureName(); std::string bmap = tex; bmap = bmap.substr(bmap.find_last_of('\\') + 1); if (type == ID_DI) m->maps[eMapType::DIFFUSE] = HWBufferManager::Instance()->LoadTexture(bmap.c_str()); else if (type == ID_BU) m->maps[eMapType::NORMAL] = HWBufferManager::Instance()->LoadTexture(bmap.c_str()); else if (type == ID_SP) m->maps[eMapType::SPECULAR] = HWBufferManager::Instance()->LoadTexture(bmap.c_str()); else if (type == ID_SI) m->maps[eMapType::EMISSIVE] = HWBufferManager::Instance()->LoadTexture(bmap.c_str()); if (type == ID_OP) m->blendMode = eBlendMode::ALPHA_TEST; TextureExporter::Instance()->Push(pMap->GetBitmapFileName()); } }