cmodfix.cpp
来自「celestia源代码」· C++ 代码 · 共 1,525 行 · 第 1/3 页
CPP
1,525 行
for (f = 0; f < nFaces; f++) { Face& face = faces[f]; for (uint32 j = 0; j < 3; j++) { vertexTangents[f * 3 + j] = averageFaceVectors(faces, f, &vertexFaces[face.vi[j]][1], vertexFaces[face.vi[j]][0], 0.0f); } } // Create the new vertex description Mesh::VertexDescription newDesc(desc); augmentVertexDescription(newDesc, Mesh::Tangent, Mesh::Float3); // We need to convert the copy the old vertex attributes to the new // mesh. In order to do this, we need the old offset of each attribute // in the new vertex description. The fromOffsets array will contain // this mapping. uint32 tangentOffset = 0; uint32 fromOffsets[16]; for (i = 0; i < newDesc.nAttributes; i++) { fromOffsets[i] = ~0; if (newDesc.attributes[i].semantic == Mesh::Tangent) { tangentOffset = newDesc.attributes[i].offset; } else { for (uint32 j = 0; j < desc.nAttributes; j++) { if (desc.attributes[j].semantic == newDesc.attributes[i].semantic) { assert(desc.attributes[j].format == newDesc.attributes[i].format); fromOffsets[i] = desc.attributes[j].offset; break; } } } } // Copy the old vertex data along with the generated tangents to the // new vertex data buffer. void* newVertexData = new char[newDesc.stride * nFaces * 3]; for (f = 0; f < nFaces; f++) { Face& face = faces[f]; for (uint32 j = 0; j < 3; j++) { char* newVertex = reinterpret_cast<char*>(newVertexData) + (f * 3 + j) * newDesc.stride; copyVertex(newVertex, newDesc, vertexData, desc, face.i[j], fromOffsets); memcpy(newVertex + tangentOffset, &vertexTangents[f * 3 + j], Mesh::getVertexAttributeSize(Mesh::Float3)); } } // Create the Celestia mesh Mesh* newMesh = new Mesh(); newMesh->setVertexDescription(newDesc); newMesh->setVertices(nFaces * 3, newVertexData); // Create a trivial index list uint32* indices = new uint32[nFaces * 3]; for (i = 0; i < nFaces * 3; i++) indices[i] = i; // TODO: This assumes that the mesh uses only one material. Tangent // generation should really be done one primitive group at a time. uint32 materialIndex = mesh.getGroup(0)->materialIndex; newMesh->addGroup(Mesh::TriList, materialIndex, nFaces * 3, indices); // Clean up delete[] faceCounts; for (i = 0; i < nVertices; i++) { if (vertexFaces[i] != NULL) delete[] vertexFaces[i]; } delete[] vertexFaces; return newMesh;}voidaddGroupWithOffset(Mesh& mesh, const Mesh::PrimitiveGroup& group, uint32 offset){ if (group.nIndices == 0) return; uint32* newIndices = new uint32[group.nIndices]; for (uint32 i = 0; i < group.nIndices; i++) newIndices[i] = group.indices[i] + offset; mesh.addGroup(group.prim, group.materialIndex, group.nIndices, newIndices);}// Merge all meshes that share the same vertex descriptionModel*mergeModelMeshes(const Model& model){ vector<Mesh*> meshes; for (uint32 i = 0; model.getMesh(i) != NULL; i++) { meshes.push_back(model.getMesh(i)); } // Sort the meshes by vertex description sort(meshes.begin(), meshes.end(), MeshVertexDescComparator()); Model* newModel = new Model(); // Copy materials into the new model for (i = 0; model.getMaterial(i) != NULL; i++) { newModel->addMaterial(model.getMaterial(i)); } uint32 meshIndex = 0; while (meshIndex < meshes.size()) { const Mesh::VertexDescription& desc = meshes[meshIndex]->getVertexDescription(); // Count the number of matching meshes uint32 nMatchingMeshes; for (nMatchingMeshes = 1; meshIndex + nMatchingMeshes < meshes.size(); nMatchingMeshes++) { if (!(meshes[meshIndex + nMatchingMeshes]->getVertexDescription() == desc)) { break; } } // Count the number of vertices in all matching meshes uint32 totalVertices = 0; uint32 j; for (j = meshIndex; j < meshIndex + nMatchingMeshes; j++) { totalVertices += meshes[j]->getVertexCount(); } char* vertexData = new char[totalVertices * desc.stride]; // Create the new empty mesh Mesh* mergedMesh = new Mesh(); mergedMesh->setVertexDescription(desc); mergedMesh->setVertices(totalVertices, vertexData); // Copy the vertex data and reindex and add primitive groups uint32 vertexCount = 0; for (j = meshIndex; j < meshIndex + nMatchingMeshes; j++) { const Mesh* mesh = meshes[j]; memcpy(vertexData + vertexCount * desc.stride, mesh->getVertexData(), mesh->getVertexCount() * desc.stride); for (uint32 k = 0; mesh->getGroup(k) != NULL; k++) { addGroupWithOffset(*mergedMesh, *mesh->getGroup(k), vertexCount); } vertexCount += mesh->getVertexCount(); } assert(vertexCount == totalVertices); newModel->addMesh(mergedMesh); meshIndex += nMatchingMeshes; } return newModel;}#ifdef TRISTRIPboolconvertToStrips(Mesh& mesh){ vector<Mesh::PrimitiveGroup*> groups; // NvTriStrip library can only handle 16-bit indices if (mesh.getVertexCount() >= 0x10000) { return true; } // Verify that the mesh contains just tri strips uint32 i; for (i = 0; mesh.getGroup(i) != NULL; i++) { if (mesh.getGroup(i)->prim != Mesh::TriList) return true; } // Convert the existing groups to triangle strips for (i = 0; mesh.getGroup(i) != NULL; i++) { const Mesh::PrimitiveGroup* group = mesh.getGroup(i); // Convert the vertex indices to shorts for the TriStrip library unsigned short* indices = new unsigned short[group->nIndices]; uint32 j; for (j = 0; j < group->nIndices; j++) { indices[j] = (unsigned short) group->indices[j]; } PrimitiveGroup* strips = NULL; unsigned short nGroups; bool r = GenerateStrips(indices, group->nIndices, &strips, &nGroups, false); if (!r || strips == NULL) { cerr << "Generate tri strips failed\n"; return false; } // Call the tristrip library to convert the lists to strips. Then, // convert from the NvTriStrip's primitive group structure to the // CMOD one and add it to the collection that will be added once // the mesh's original primitive groups are cleared. for (j = 0; j < nGroups; j++) { Mesh::PrimitiveGroupType prim = Mesh::InvalidPrimitiveGroupType; switch (strips[j].type) { case PT_LIST: prim = Mesh::TriList; break; case PT_STRIP: prim = Mesh::TriStrip; break; case PT_FAN: prim = Mesh::TriFan; break; } if (prim != Mesh::InvalidPrimitiveGroupType && strips[j].numIndices != 0) { Mesh::PrimitiveGroup* newGroup = new Mesh::PrimitiveGroup(); newGroup->prim = prim; newGroup->materialIndex = group->materialIndex; newGroup->nIndices = strips[j].numIndices; newGroup->indices = new uint32[newGroup->nIndices]; for (uint32 k = 0; k < newGroup->nIndices; k++) newGroup->indices[k] = strips[j].indices[k]; groups.push_back(newGroup); } } delete[] strips; } mesh.clearGroups(); // Add the stripified groups to the mesh for (vector<Mesh::PrimitiveGroup*>::const_iterator iter = groups.begin(); iter != groups.end(); iter++) { mesh.addGroup(*iter); } return true;}#endifbool parseCommandLine(int argc, char* argv[]){ int i = 1; int fileCount = 0; while (i < argc) { if (argv[i][0] == '-') { if (!strcmp(argv[i], "-b") || !strcmp(argv[i], "--binary")) { outputBinary = true; } else if (!strcmp(argv[i], "-a") || !strcmp(argv[i], "--ascii")) { outputBinary = false; } else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--uniquify")) { uniquify = true; } else if (!strcmp(argv[i], "-n") || !strcmp(argv[i], "--normals")) { genNormals = true; } else if (!strcmp(argv[i], "-t") || !strcmp(argv[i], "--tangents")) { genTangents = true; } else if (!strcmp(argv[i], "-w") || !strcmp(argv[i], "--weld")) { weldVertices = true; } else if (!strcmp(argv[i], "-m") || !strcmp(argv[i], "--merge")) { mergeMeshes = true; } else if (!strcmp(argv[i], "-o") || !strcmp(argv[i], "--optimize")) { stripify = true; } else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--smooth")) { if (i == argc - 1) { return false; } else { if (sscanf(argv[i + 1], " %f", &smoothAngle) != 1) return false; i++; } } else { return false; } i++; } else { if (fileCount == 0) { // input filename first inputFilename = string(argv[i]); fileCount++; } else if (fileCount == 1) { // output filename second outputFilename = string(argv[i]); fileCount++; } else { // more than two filenames on the command line is an error return false; } i++; } } return true;}int main(int argc, char* argv[]){ if (!parseCommandLine(argc, argv)) { usage(); return 1; } Model* model = NULL; if (!inputFilename.empty()) { ifstream in(inputFilename.c_str(), ios::in | ios::binary); if (!in.good()) { cerr << "Error opening " << inputFilename << "\n"; return 1; } model = LoadModel(in); } else { model = LoadModel(cin); } if (model == NULL) return 1; if (genNormals || genTangents) { Model* newModel = new Model(); uint32 i; // Copy materials for (i = 0; model->getMaterial(i) != NULL; i++) { newModel->addMaterial(model->getMaterial(i)); } // Generate normals and/or tangents for each model in the mesh for (i = 0; model->getMesh(i) != NULL; i++) { Mesh* mesh = model->getMesh(i); Mesh* newMesh = NULL; if (genNormals) { newMesh = generateNormals(*mesh, degToRad(smoothAngle), weldVertices); if (newMesh == NULL) { cerr << "Error generating normals!\n"; return 1; } // TODO: clean up old mesh mesh = newMesh; } if (genTangents) { newMesh = generateTangents(*mesh, weldVertices); if (newMesh == NULL) { cerr << "Error generating tangents!\n"; return 1; } // TODO: clean up old mesh mesh = newMesh; } newModel->addMesh(mesh); } // delete model; model = newModel; } if (mergeMeshes) { model = mergeModelMeshes(*model); } if (uniquify) { for (uint32 i = 0; model->getMesh(i) != NULL; i++) { Mesh* mesh = model->getMesh(i); uniquifyVertices(*mesh); } }#ifdef TRISTRIP if (stripify) { SetCacheSize(vertexCacheSize); for (uint32 i = 0; model->getMesh(i) != NULL; i++) { Mesh* mesh = model->getMesh(i); convertToStrips(*mesh); } }#endif if (outputFilename.empty()) { if (outputBinary) SaveModelBinary(model, cout); else SaveModelAscii(model, cout); } else { ofstream out(outputFilename.c_str(), ios::out | (outputBinary ? ios::binary : 0)); if (!out.good()) { cerr << "Error opening output file " << outputFilename << "\n"; return 1; } if (outputBinary) SaveModelBinary(model, out); else SaveModelAscii(model, out); } return 0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?