renderer::MeshObject *convert( const IECore::Object *primitive ) { assert( primitive->typeId() == IECore::MeshPrimitiveTypeId ); const IECore::MeshPrimitive *mesh = static_cast<const IECore::MeshPrimitive *>( primitive ); const V3fVectorData *p = mesh->variableData<V3fVectorData>( "P", PrimitiveVariable::Vertex ); if( !p ) { throw Exception( "MeshPrimitive does not have \"P\" primitive variable of interpolation type Vertex." ); } asf::auto_release_ptr<asr::MeshObject> meshEntity = asr::MeshObjectFactory::create( "mesh", asr::ParamArray() ); const size_t materialSlot = meshEntity->push_material_slot( "default" ); // vertices { size_t numVertices = p->readable().size(); meshEntity->reserve_vertices( numVertices ); const std::vector<V3f> &points = p->readable(); for( size_t i = 0; i < numVertices; ++i ) { meshEntity->push_vertex( asr::GVector3( points[i].x, points[i].y, points[i].z ) ); } } // triangulate primitive (this should be in appleseed at some point) MeshPrimitivePtr triangulatedMeshPrimPtr = mesh->copy(); { TriangulateOpPtr op = new TriangulateOp(); op->inputParameter()->setValue( triangulatedMeshPrimPtr ); op->throwExceptionsParameter()->setTypedValue( false ); // it's better to see something than nothing op->copyParameter()->setTypedValue( false ); op->operate(); } // triangles size_t numTriangles = triangulatedMeshPrimPtr->numFaces(); std::vector<asr::Triangle> triangles; triangles.reserve( numTriangles ); const std::vector<int> &vidx = triangulatedMeshPrimPtr->vertexIds()->readable(); for( size_t i = 0; i < vidx.size(); i += 3 ) { triangles.push_back( asr::Triangle( vidx[i], vidx[i+1], vidx[i+2], materialSlot ) ); } // texture coords { const FloatVectorData *s = triangulatedMeshPrimPtr->variableData<FloatVectorData>( "s" ); const FloatVectorData *t = triangulatedMeshPrimPtr->variableData<FloatVectorData>( "t" ); if( s && t ) { PrimitiveVariable::Interpolation sInterpolation = triangulatedMeshPrimPtr->variables.find( "s" )->second.interpolation; PrimitiveVariable::Interpolation tInterpolation = triangulatedMeshPrimPtr->variables.find( "t" )->second.interpolation; if( sInterpolation == tInterpolation ) { if( sInterpolation == PrimitiveVariable::Varying || sInterpolation == PrimitiveVariable::Vertex || sInterpolation == PrimitiveVariable::FaceVarying ) { size_t numSTs = s->readable().size(); meshEntity->reserve_tex_coords( numSTs ); const std::vector<float> &svec = s->readable(); const std::vector<float> &tvec = t->readable(); for( size_t i = 0; i < numSTs; ++i) { meshEntity->push_tex_coords( asr::GVector2( svec[i], 1.0f - tvec[i] ) ); } if( sInterpolation == PrimitiveVariable::FaceVarying ) { for( size_t i = 0, j = 0; i < numTriangles; ++i) { asr::Triangle& tri = triangles[i]; tri.m_a0 = j++; tri.m_a1 = j++; tri.m_a2 = j++; } } else { for( size_t i = 0; i < vidx.size(); i += 3) { asr::Triangle& tri = triangles[i / 3]; tri.m_a0 = vidx[i]; tri.m_a1 = vidx[i+1]; tri.m_a2 = vidx[i+2]; } } } else { msg( Msg::Warning, "ToAppleseedMeshConverter::doConversion", "Variables s and t have unsupported interpolation type - not generating uvs." ); } } else { msg( Msg::Warning, "ToAppleseedMeshConverter::doConversion", "Variables s and t have different interpolation - not generating uvs." ); } } else if( s || t ) { msg( Msg::Warning, "ToAppleseedMeshConverter::doConversion", "Only one of s and t available - not generating uvs." ); } } // normals { PrimitiveVariableMap::const_iterator nIt = triangulatedMeshPrimPtr->variables.find( "N" ); if( nIt != triangulatedMeshPrimPtr->variables.end() ) { const V3fVectorData *n = runTimeCast<const V3fVectorData>( nIt->second.data.get() ); if( n ) { PrimitiveVariable::Interpolation nInterpolation = nIt->second.interpolation; if( nInterpolation == PrimitiveVariable::Varying || nInterpolation == PrimitiveVariable::Vertex || nInterpolation == PrimitiveVariable::FaceVarying ) { size_t numNormals = n->readable().size(); meshEntity->reserve_vertex_normals( numNormals ); const std::vector<V3f> &normals = n->readable(); for( size_t i = 0; i < numNormals; ++i) { asr::GVector3 n( normals[i].x, normals[i].y, normals[i].z ); meshEntity->push_vertex_normal( asf::normalize( n ) ); } if( nInterpolation == PrimitiveVariable::FaceVarying ) { for( size_t i = 0, j = 0; i < numTriangles; ++i) { asr::Triangle& tri = triangles[i]; tri.m_n0 = j++; tri.m_n1 = j++; tri.m_n2 = j++; } } else { for( size_t i = 0; i < vidx.size(); i += 3) { asr::Triangle& tri = triangles[i / 3]; tri.m_n0 = vidx[i]; tri.m_n1 = vidx[i+1]; tri.m_n2 = vidx[i+2]; } } } else { msg( Msg::Warning, "ToAppleseedMeshConverter::doConversion", "Variable \"N\" has unsupported interpolation type - not generating normals." ); } } else { msg( Msg::Warning, "ToAppleseedMeshConverter::doConversion", boost::format( "Variable \"N\" has unsupported type \"%s\" (expected V3fVectorData)." ) % nIt->second.data->typeName() ); } } } // tangents { PrimitiveVariableMap::const_iterator tIt = triangulatedMeshPrimPtr->variables.find( "uTangent" ); if( tIt != triangulatedMeshPrimPtr->variables.end() ) { const V3fVectorData *t = runTimeCast<const V3fVectorData>( tIt->second.data.get() ); if( t ) { PrimitiveVariable::Interpolation tInterpolation = tIt->second.interpolation; if( tInterpolation == PrimitiveVariable::Varying || tInterpolation == PrimitiveVariable::Vertex ) { size_t numTangents = t->readable().size(); meshEntity->reserve_vertex_tangents( numTangents ); const std::vector<V3f> &tangents = t->readable(); for( size_t i = 0; i < numTangents; ++i) { asr::GVector3 t( tangents[i].x, tangents[i].y, tangents[i].z ); meshEntity->push_vertex_tangent( asf::normalize( t ) ); } } else { msg( Msg::Warning, "ToAppleseedMeshConverter::doConversion", "Variable \"uTangent\" has unsupported interpolation type - not generating tangents." ); } } else { msg( Msg::Warning, "ToAppleseedMeshConverter::doConversion", boost::format( "Variable \"uTangent\" has unsupported type \"%s\" (expected V3fVectorData)." ) % tIt->second.data->typeName() ); } } } // copy triangles to mesh entity { meshEntity->reserve_triangles( numTriangles ); for( size_t i = 0; i < triangles.size(); ++i) { meshEntity->push_triangle( triangles[i] ); } } return meshEntity.release(); }
void GXEvaluator::buildSTEvaluator() const { Mutex::scoped_lock lock( m_stEvaluatorMutex, false ); // read only lock if( m_stEvaluator ) { return; } lock.upgrade_to_writer(); if( m_stEvaluator ) { return; } size_t nFaces = numFaces(); size_t nVertices = nFaces * 4; IntVectorDataPtr faceIndicesData = new IntVectorData; FloatVectorDataPtr uData = new FloatVectorData; FloatVectorDataPtr vData = new FloatVectorData; std::vector<int> &faceIndicesWritable = faceIndicesData->writable(); faceIndicesWritable.resize( nVertices ); std::vector<float> &uWritable = uData->writable(); uWritable.resize( nVertices ); std::vector<float> &vWritable = vData->writable(); vWritable.resize( nVertices ); size_t vi = 0; for( size_t fi=0; fi<nFaces; fi++ ) { faceIndicesWritable[vi] = fi; faceIndicesWritable[vi+1] = fi; faceIndicesWritable[vi+2] = fi; faceIndicesWritable[vi+3] = fi; uWritable[vi] = 0; uWritable[vi+1] = 0; uWritable[vi+2] = 1; uWritable[vi+3] = 1; vWritable[vi] = 0; vWritable[vi+1] = 1; vWritable[vi+2] = 1; vWritable[vi+3] = 0; vi += 4; } std::vector<std::string> primVarNames; primVarNames.push_back( "P" ); primVarNames.push_back( "s" ); primVarNames.push_back( "t" ); CompoundDataPtr vertexData = evaluate( faceIndicesData, uData, vData, primVarNames ); IntVectorDataPtr verticesPerFaceData = new IntVectorData; IntVectorDataPtr vertexIdsData = new IntVectorData; std::vector<int> &verticesPerFace = verticesPerFaceData->writable(); verticesPerFace.resize( nFaces, 4 ); std::vector<int> &vertexIds = vertexIdsData->writable(); vertexIds.resize( nVertices ); for( size_t i=0; i<nVertices; i++ ) { vertexIds[i] = i; } MeshPrimitivePtr mesh = new MeshPrimitive( verticesPerFaceData, vertexIdsData ); mesh->variables["P"] = PrimitiveVariable( PrimitiveVariable::Vertex, vertexData->member<V3fVectorData>( "P" ) ); mesh->variables["s"] = PrimitiveVariable( PrimitiveVariable::FaceVarying, vertexData->member<FloatVectorData>( "s" ) ); mesh->variables["t"] = PrimitiveVariable( PrimitiveVariable::FaceVarying, vertexData->member<FloatVectorData>( "t" ) ); mesh->variables["u"] = PrimitiveVariable( PrimitiveVariable::Vertex, uData ); mesh->variables["v"] = PrimitiveVariable( PrimitiveVariable::Vertex, vData ); TriangulateOpPtr op = new TriangulateOp(); op->inputParameter()->setValue( mesh ); op->copyParameter()->setTypedValue( false ); op->throwExceptionsParameter()->setTypedValue( false ); op->operate(); m_stEvaluator = new MeshPrimitiveEvaluator( mesh ); }