From 3dc550a9b2b4a0ac4f138dadea7a595985a25368 Mon Sep 17 00:00:00 2001 From: Trevor David Black Date: Sat, 25 Apr 2020 00:10:31 -0700 Subject: [PATCH] Got a working geometry prototype, sponza renders correctly when camera and light is added --- code/Common/Exporter.cpp | 2 +- code/Pbrt/PbrtExporter.cpp | 216 ++++++++++++++++++++++++++++++++----- code/Pbrt/PbrtExporter.h | 10 +- 3 files changed, 195 insertions(+), 33 deletions(-) diff --git a/code/Common/Exporter.cpp b/code/Common/Exporter.cpp index fca7b716d..79beff74a 100644 --- a/code/Common/Exporter.cpp +++ b/code/Common/Exporter.cpp @@ -189,7 +189,7 @@ static void setupExporterArray(std::vector &exporte #endif #ifndef ASSIMP_BUILD_NO_PBRT_EXPORTER - exporters.push_back(Exporter::ExportFormatEntry("pbrt", "Pbrt scene description file", "pbrt", &ExportScenePbrt, 0)); + exporters.push_back(Exporter::ExportFormatEntry("pbrt", "Pbrt scene description file", "pbrt", &ExportScenePbrt, aiProcess_Triangulate | aiProcess_SortByPType)); #endif #ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER diff --git a/code/Pbrt/PbrtExporter.cpp b/code/Pbrt/PbrtExporter.cpp index 1dcbad0ec..7d3794765 100644 --- a/code/Pbrt/PbrtExporter.cpp +++ b/code/Pbrt/PbrtExporter.cpp @@ -311,6 +311,7 @@ void PbrtExporter::WriteCamera(int i) { // Get camera transform // Isn't optimally efficient, but is the simplest implementation // Get camera node + aiMatrix4x4 w2c; auto cameraNode = mScene->mRootNode->FindNode(camera->mName); if (!cameraNode) { mOutput << "# ERROR: Camera declared but not found in scene tree" << std::endl; @@ -323,22 +324,29 @@ void PbrtExporter::WriteCamera(int i) { tempNode = tempNode->mParent; } - aiMatrix4x4 w2c = matrixChain[0]; + w2c = matrixChain[0]; for(int i = 1; i < matrixChain.size(); i++){ w2c *= matrixChain[i]; } - - if (!cameraActive) - mOutput << "# "; - - mOutput << "Transform [" - << w2c.a1 << " " << w2c.a2 << " " << w2c.a3 << " " << w2c.a4 << " " - << w2c.b1 << " " << w2c.b2 << " " << w2c.b3 << " " << w2c.b4 << " " - << w2c.c1 << " " << w2c.c2 << " " << w2c.c3 << " " << w2c.c4 << " " - << w2c.d1 << " " << w2c.d2 << " " << w2c.d3 << " " << w2c.d4 - << "]" << std::endl; } + // Print Camera LookAt + auto position = w2c * camera->mPosition; + auto lookAt = w2c * camera->mLookAt; + auto up = w2c * camera->mUp; + if (!cameraActive) + mOutput << "# "; + mOutput << "LookAt " + << position.x << " " << position.y << " " << position.z << std::endl; + if (!cameraActive) + mOutput << "# "; + mOutput << " " + << lookAt.x << " " << lookAt.y << " " << lookAt.z << std::endl; + if (!cameraActive) + mOutput << "# "; + mOutput << " " + << up.x << " " << up.y << " " << up.z << std::endl; + // Print camera descriptor if(!cameraActive) mOutput << "# "; @@ -355,6 +363,7 @@ void PbrtExporter::WriteGeometry() { // bool mIOSystem->CreateDirectory(path) // TODO worry about sequestering geo later, after giant print + // TODO rewrite as WriteShapes & WriteShape } void PbrtExporter::WriteWorldDefinition() { @@ -372,13 +381,15 @@ void PbrtExporter::WriteWorldDefinition() { // Print materials WriteMaterials(); + // Print Objects + // Both PBRT's `Shape` and `Object` are in Assimp's `aiMesh` class + WriteObjects(); + + // Print Object Instancing (nodes) + WriteObjectInstances(); + // Print Lights (w/o geometry) WriteLights(); - - // Print Shapes - WriteShapes(); - - // Print Object Instancing (no emissive) // Print Area Lights (w/ geometry) @@ -427,7 +438,7 @@ void PbrtExporter::WriteMaterials() { } void PbrtExporter::WriteMaterial(int i) { - // TODO + // TODO IMMEDIATELY // Use MakeNamedMaterial to give variable names to materials } @@ -444,15 +455,15 @@ void PbrtExporter::WriteLights() { // TODO remove default ambient term when numCameras == 0 // For now, ambient may only be necessary for debug mOutput << "# - Creating a default blueish ambient light source" << std::endl; - mOutput << "LightSource \"infinite\" \"rgb L\" [.4 .45 .5]" << std::endl; - + mOutput << "LightSource \"infinite\" \"rgb L\" [0.4 0.45 0.5]" << std::endl; + mOutput << " \"integer samples\" [8]" << std::endl; } -void PbrtExporter::WriteShapes() { +void PbrtExporter::WriteObjects() { mOutput << std::endl; - mOutput << "#################" << std::endl; - mOutput << "# Writing Shapes:" << std::endl; - mOutput << "#################" << std::endl; + mOutput << "#############################" << std::endl; + mOutput << "# Writing Object Definitions:" << std::endl; + mOutput << "#############################" << std::endl; mOutput << "# - Number of Meshes found in scene: "; mOutput << mScene->mNumMeshes << std::endl; @@ -460,17 +471,164 @@ void PbrtExporter::WriteShapes() { return; for (int i = 0 ; i < mScene->mNumMeshes; i++) { - WriteShape(i); + WriteObject(i); } } -void PbrtExporter::WriteShape(int i) { - // TODO IMMEDIATELY +void PbrtExporter::WriteObject(int i) { + auto mesh = mScene->mMeshes[i]; + mOutput << "# - Mesh " << i+1 << ": "; + if (mesh->mName == aiString("")) + mOutput << "" << std::endl; + else + mOutput << mesh->mName.C_Str() << std::endl; + + // Print out primitive types found + mOutput << "# - Primitive Type(s):" << std::endl; + if (mesh->mPrimitiveTypes & aiPrimitiveType_POINT) + mOutput << "# - POINT" << std::endl; + if (mesh->mPrimitiveTypes & aiPrimitiveType_LINE) + mOutput << "# - LINE" << std::endl; + if (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE) + mOutput << "# - TRIANGLE" << std::endl; + if (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON) + mOutput << "# - POLYGON" << std::endl; + // Check if any types other than tri + if ( (mesh->mPrimitiveTypes & aiPrimitiveType_POINT) + || (mesh->mPrimitiveTypes & aiPrimitiveType_LINE) + || (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) { + mOutput << "# ERROR: PBRT Does not support POINT, LINE, POLY meshes" << std::endl; + } + + // Check for Normals + mOutput << "# - Normals: "; + if (mesh->mNormals) + mOutput << "TRUE" << std::endl; + else + mOutput << "FALSE" << std::endl; - // if aiPrimtiveType == Tri -> you're fine - // if aiPrimitiveType == Poly -> use aiProcess_triangulate - // if aiPrimitiveType == anything else -> throw error + // Check for Tangents + mOutput << "# - Tangents: "; + if (mesh->mTangents) + mOutput << "TRUE" << std::endl; + else + mOutput << "FALSE" << std::endl; + + // Count number of texture coordinates + int numTextureCoords = 0; + for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) { + if (mesh->mTextureCoords[i]) + numTextureCoords++; + } + mOutput << "# - Number of Texture Coordinates: " + << numTextureCoords << std::endl; + if (numTextureCoords > 1) { + mOutput << "# - Multiple Texture Coordinates found in scene" << std::endl; + mOutput << "# - Defaulting to first Texture Coordinate specified" << std::endl; + } + + // Check for Alpha texture + mOutput << "# - Alpha texture: " << std::endl; + // TODO + + // Create ObjectBegin + mOutput << "ObjectBegin \""; + if (mesh->mName == aiString("")) + mOutput << "mesh_" << i+1 << "\"" << std::endl; + else + mOutput << mesh->mName.C_Str() << "_" << i+1 << "\"" << std::endl; + + // Write Shapes + mOutput << "Shape \"trianglemesh\"" << std::endl + << " \"integer indices\" ["; + // Start with faces (which hold indices) + for(int i = 0; i < mesh->mNumFaces; i++) { + auto face = mesh->mFaces[i]; + for(int j = 0; j < face.mNumIndices; j++) { + mOutput << face.mIndices[j] << " "; + } + } + mOutput << "]" << std::endl; + // Then go to vertices + mOutput << " \"point P\" ["; + for(int i = 0; i < mesh->mNumVertices; i++) { + auto vector = mesh->mVertices[i]; + mOutput << vector.x << " " << vector.y << " " << vector.z << " "; + } + mOutput << "]" << std::endl; + // Normals (if present) + if (mesh->mNormals) { + mOutput << " \"normal N\" ["; + for(int i = 0; i < mesh->mNumVertices; i++) { + auto normal = mesh->mNormals[i]; + mOutput << normal.x << " " << normal.y << " " << normal.z << " "; + } + mOutput << "]" << std::endl; + } + // Tangents (if present) + if (mesh->mTangents) { + mOutput << " \"vector S\" ["; + for(int i = 0; i < mesh->mNumVertices; i++) { + auto tangent = mesh->mTangents[i]; + mOutput << tangent.x << " " << tangent.y << " " << tangent.z << " "; + } + mOutput << "]" << std::endl; + } + // Texture Coords (if present) + // TODO comment out wrong ones, only choose 1st 2d texture coord + + + // Close ObjectBegin + mOutput << "ObjectEnd" << std::endl; +} + +void PbrtExporter::WriteObjectInstances() { + mOutput << std::endl; + mOutput << "###########################" << std::endl; + mOutput << "# Writing Object Instances:" << std::endl; + mOutput << "###########################" << std::endl; + + // Get root node of the scene + auto rootNode = mScene->mRootNode; + + // Set base transform to identity + aiMatrix4x4 parentTransform; + + // Recurse into root node + WriteObjectInstance(rootNode, parentTransform); +} + +void PbrtExporter::WriteObjectInstance(aiNode* node, aiMatrix4x4 parent) { + // TODO IMMEDIATELY fix transforms for nodes + + auto w2o = parent * node->mTransformation; + + // Print transformation for this node + if(node->mNumMeshes > 0) { + mOutput << "Transform [" + << w2o.a1 << " " << w2o.a2 << " " << w2o.a3 << " " << w2o.a4 << " " + << w2o.b1 << " " << w2o.b2 << " " << w2o.b3 << " " << w2o.b4 << " " + << w2o.c1 << " " << w2o.c2 << " " << w2o.c3 << " " << w2o.c4 << " " + << w2o.d1 << " " << w2o.d2 << " " << w2o.d3 << " " << w2o.d4 + << "]" << std::endl; + } + + // Loop over number of meshes in node + for(int i = 0; i < node->mNumMeshes; i++) { + // Print ObjectInstance + mOutput << "ObjectInstance \""; + auto mesh = mScene->mMeshes[node->mMeshes[i]]; + if (mesh->mName == aiString("")) + mOutput << "mesh_" << node->mMeshes[i] + 1 << "\"" << std::endl; + else + mOutput << mesh->mName.C_Str() << "_" << node->mMeshes[i] + 1 << "\"" << std::endl; + } + + // Recurse through children + for (int i = 0; i < node->mNumChildren; i++) { + WriteObjectInstance(node->mChildren[i], w2o); + } } #endif // ASSIMP_BUILD_NO_PBRT_EXPORTER diff --git a/code/Pbrt/PbrtExporter.h b/code/Pbrt/PbrtExporter.h index fca02177a..6621f78ca 100644 --- a/code/Pbrt/PbrtExporter.h +++ b/code/Pbrt/PbrtExporter.h @@ -128,9 +128,13 @@ private: // Writing the Light data void WriteLights(); - // Writing the Shape data - void WriteShapes(); - void WriteShape(int i); + // Writing the Object data + void WriteObjects(); + void WriteObject(int i); + + // Writing the Object Instances + void WriteObjectInstances(); + void WriteObjectInstance(aiNode* node, aiMatrix4x4 parentTransform); }; } // namespace Assimp