/*========================================================================= Program: Visualization Toolkit Module: vtkOSPRayPolyDataMapperNode.cxx Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkOSPRayPolyDataMapperNode.h" #include "vtkActor.h" #include "vtkOSPRayActorNode.h" #include "vtkOSPRayMaterialHelpers.h" #include "vtkOSPRayRendererNode.h" #include "vtkDataArray.h" #include "vtkFloatArray.h" #include "vtkImageData.h" #include "vtkInformation.h" #include "vtkInformationDoubleKey.h" #include "vtkInformationObjectBaseKey.h" #include "vtkMapper.h" #include "vtkObjectFactory.h" #include "vtkPiecewiseFunction.h" #include "vtkPointData.h" #include "vtkPolyData.h" #include "vtkProperty.h" #include "vtkRenderer.h" #include "vtkTexture.h" #include "vtkScalarsToColors.h" #include "vtkSmartPointer.h" #include "ospray/ospray.h" #include "ospray/version.h" #include //============================================================================ namespace vtkosp { //------------------------------------------------------------------------------ class MyGeom { //A cache for the ospray meshes we make for this actor. //When something else in the scene changes but this actor doesn't we //reuse instead of recreating. RendererNode has a higher level cache //that prevent spatial sorting when nothing changes other than camera. public: std::vector geoms; ~MyGeom() { std::vector::iterator it = geoms.begin(); while (it != geoms.end()) { ospRelease((OSPGeometry)*it); ++it; } geoms.clear(); } void Add(OSPGeometry geo) { geoms.push_back(geo); } void AddMyselfTo(OSPModel oModel) { std::vector::iterator it = geoms.begin(); while (it != geoms.end()) { ospAddGeometry(oModel, *it); ++it; } } }; //------------------------------------------------------------------------------ void VToOPointNormals( vtkDataArray *vNormals, osp::vec3f *&normals) { int numNormals = vNormals->GetNumberOfTuples(); normals = new osp::vec3f[numNormals]; for (int i = 0; i < numNormals; i++) { double *vNormal = vNormals->GetTuple(i); normals[i] = osp::vec3f { static_cast(vNormal[0]), static_cast(vNormal[1]), static_cast(vNormal[2]) }; } } //------------------------------------------------------------------------------ void CellMaterials( vtkPolyData *poly, vtkMapper *mapper, vtkScalarsToColors *s2c, std::map mats, OSPRenderer oRenderer, std::vector &ospMaterials, vtkUnsignedCharArray *vColors, float *specColor, float specPower, float opacity ) { vtkAbstractArray *scalars = nullptr; bool try_mats = s2c->GetIndexedLookup() && s2c->GetNumberOfAnnotatedValues() && mats.size()>0; if (try_mats) { int cflag2 =-1; scalars = mapper->GetAbstractScalars (poly, mapper->GetScalarMode(), mapper->GetArrayAccessMode(), mapper->GetArrayId(), mapper->GetArrayName(), cflag2); } int numColors = vColors->GetNumberOfTuples(); for (int i = 0; i < numColors; i++) { bool found = false; if (scalars) { vtkVariant v = scalars->GetVariantValue(i); vtkIdType idx = s2c->GetAnnotatedValueIndex(v); if (idx > -1) { std::string name(s2c->GetAnnotation(idx)); if (mats.find(name) != mats.end()) { OSPMaterial oMaterial = mats[name]; ospCommit(oMaterial); ospMaterials.push_back(oMaterial); found = true; } } } if (!found) { double *color = vColors->GetTuple(i); OSPMaterial oMaterial; oMaterial = ospNewMaterial(oRenderer,"OBJMaterial"); float diffusef[] = { static_cast(color[0])/(255.0f), static_cast(color[1])/(255.0f), static_cast(color[2])/(255.0f) }; ospSet3fv(oMaterial,"Kd",diffusef); float specAdjust = 2.0f/(2.0f+specPower); float specularf[] = { specColor[0]*specAdjust, specColor[1]*specAdjust, specColor[2]*specAdjust }; ospSet3fv(oMaterial,"Ks",specularf); ospSet1f(oMaterial,"Ns",specPower); ospSet1f(oMaterial,"d", opacity); ospCommit(oMaterial); ospMaterials.push_back(oMaterial); } } } //---------------------------------------------------------------------------- float MapThroughPWF(double in, vtkPiecewiseFunction *scaleFunction) { double out = in; if (!scaleFunction) { out = in; } else { out = scaleFunction->GetValue(in); } return static_cast(out); } //---------------------------------------------------------------------------- OSPGeometry RenderAsSpheres(osp::vec3fa *vertices, std::vector &indexArray, std::vector &rIndexArray, double pointSize, vtkDataArray* scaleArray, vtkPiecewiseFunction *scaleFunction, bool useCustomMaterial, OSPMaterial actorMaterial, vtkImageData *vColorTextureMap, int numTextureCoordinates, float *textureCoordinates, int numCellMaterials, OSPData CellMaterials, int numPointColors, osp::vec4f *PointColors, int numPointValueTextureCoords, float *pointValueTextureCoords, OSPModel oModel, OSPRenderer oRenderer ) { OSPGeometry ospMesh = ospNewGeometry("spheres"); int width=4; int scaleOffset = -1; if (scaleArray != nullptr) { width = 5; scaleOffset = 4*sizeof(float); } float *mdata = new float[width*indexArray.size()]; int *idata = (int*)mdata; for (size_t i = 0; i < indexArray.size(); i++) { mdata[i*width+0] = static_cast(vertices[indexArray[i]].x); mdata[i*width+1] = static_cast(vertices[indexArray[i]].y); mdata[i*width+2] = static_cast(vertices[indexArray[i]].z); int mat = 0; if (numCellMaterials) { mat = rIndexArray[i]; } else if (numPointColors) { mat = indexArray[i]; } idata[i*width+3] = mat; if (scaleArray != nullptr) { mdata[i*width+4] = MapThroughPWF (*scaleArray->GetTuple(indexArray[i]), scaleFunction); } } OSPData _PointColors = nullptr; if (numPointColors) { _PointColors = ospNewData(numPointColors, OSP_FLOAT4, &PointColors[0]); } OSPData _mdata = ospNewData(indexArray.size()*width, OSP_FLOAT, mdata); ospSetObject(ospMesh, "spheres", _mdata); ospSet1i(ospMesh, "bytes_per_sphere", width*sizeof(float)); ospSet1i(ospMesh, "offset_center", 0*sizeof(float)); ospSet1f(ospMesh, "radius", pointSize); ospSet1i(ospMesh, "offset_radius", scaleOffset); //send the texture map and texture coordinates over bool _hastm = false; osp::vec2f *tc = nullptr; if (numTextureCoordinates || numPointValueTextureCoords) { _hastm = true; if (numPointValueTextureCoords) { //using 1D texture for point value LUT tc = new osp::vec2f[indexArray.size()]; for (size_t i = 0; i < indexArray.size(); i++) { float t1; int index1 = indexArray[i]; t1 = pointValueTextureCoords[index1+0]; tc[i] = osp::vec2f{t1,0}; } OSPData tcs = ospNewData(indexArray.size(), OSP_FLOAT2, &tc[0]); ospSetData(ospMesh, "texcoord", tcs); } else if (numTextureCoordinates) { //2d texture mapping float *itc = textureCoordinates; tc = new osp::vec2f[indexArray.size()]; for (size_t i = 0; i < indexArray.size(); i++) { float t1,t2; int index1 = indexArray[i]; t1 = itc[index1*2+0]; t2 = itc[index1*2+1]; tc[i] = osp::vec2f{t1,t2}; } OSPData tcs = ospNewData(indexArray.size(), OSP_FLOAT2, &tc[0]); ospSetData(ospMesh, "texcoord", tcs); } } delete[] tc; if (useCustomMaterial) { ospSetMaterial(ospMesh, actorMaterial); } else if (vColorTextureMap && _hastm) { osp::Texture2D *t2d = vtkOSPRayMaterialHelpers::VTKToOSPTexture(vColorTextureMap); OSPMaterial ospMaterial = ospNewMaterial(oRenderer,"OBJMaterial"); ospSetObject(ospMaterial, "map_Kd", ((OSPTexture2D)(t2d))); ospCommit(t2d); ospCommit(ospMaterial); ospSetMaterial(ospMesh, ospMaterial); } else if (numCellMaterials) { //per cell color ospSet1i(ospMesh, "offset_materialID", 3*sizeof(float)); ospSetData(ospMesh, "materialList", CellMaterials); } else if (numPointColors) { //per point color ospSet1i(ospMesh, "offset_colorID", 3*sizeof(float)); ospSetData(ospMesh, "color", _PointColors); } else { //per actor color ospSetMaterial(ospMesh, actorMaterial); } ospAddGeometry(oModel, ospMesh); ospCommit(ospMesh); ospRelease(_PointColors); ospRelease(_mdata); delete[] mdata; return ospMesh; } //---------------------------------------------------------------------------- OSPGeometry RenderAsCylinders(osp::vec3fa *vertices, std::vector &indexArray, std::vector &rIndexArray, double lineWidth, vtkDataArray *scaleArray, vtkPiecewiseFunction *scaleFunction, bool useCustomMaterial, OSPMaterial actorMaterial, vtkImageData *vColorTextureMap, int numTextureCoordinates, float *textureCoordinates, int numCellMaterials, OSPData CellMaterials, int numPointColors, osp::vec4f *PointColors, int numPointValueTextureCoords, float *pointValueTextureCoords, OSPModel oModel, OSPRenderer oRenderer ) { OSPGeometry ospMesh = ospNewGeometry("cylinders"); int width=7; int scaleOffset = -1; if (scaleArray != nullptr) { width = 8; scaleOffset = 7*sizeof(float); } float *mdata = new float[indexArray.size()/2*width]; int *idata = (int*)mdata; for (size_t i = 0; i < indexArray.size()/2; i++) { mdata[i*width+0] = static_cast(vertices[indexArray[i*2+0]].x); mdata[i*width+1] = static_cast(vertices[indexArray[i*2+0]].y); mdata[i*width+2] = static_cast(vertices[indexArray[i*2+0]].z); mdata[i*width+3] = static_cast(vertices[indexArray[i*2+1]].x); mdata[i*width+4] = static_cast(vertices[indexArray[i*2+1]].y); mdata[i*width+5] = static_cast(vertices[indexArray[i*2+1]].z); int mat = 0; if (numCellMaterials) { mat = rIndexArray[i*2]; } else if (numPointColors) { mat = indexArray[i*2]; } idata[i*width+6] = mat; if (scaleArray != nullptr) { double avg = (*scaleArray->GetTuple(indexArray[i*2+0]) + *scaleArray->GetTuple(indexArray[i*2+1]))*0.5; mdata[i*width+7] = MapThroughPWF (avg, scaleFunction); } } OSPData _PointColors = nullptr; if (numPointColors) { _PointColors = ospNewData(numPointColors, OSP_FLOAT4, &PointColors[0]); } OSPData _mdata = ospNewData(indexArray.size()/2*width, OSP_FLOAT, mdata); ospSetData(ospMesh, "cylinders", _mdata); ospSet1i(ospMesh, "bytes_per_cylinder", width*sizeof(float)); ospSet1i(ospMesh, "offset_v0", 0); ospSet1i(ospMesh, "offset_v1", 3*sizeof(float)); ospSet1f(ospMesh, "radius", lineWidth); ospSet1i(ospMesh, "offset_radius", scaleOffset); //send the texture map and texture coordinates over bool _hastm = false; osp::vec2f *tc = nullptr; if (numTextureCoordinates || numPointValueTextureCoords) { _hastm = true; if (numPointValueTextureCoords) { //using 1D texture for point value LUT tc = new osp::vec2f[indexArray.size()]; for (size_t i = 0; i < indexArray.size(); i+=2) { float t1,t2; int index1 = indexArray[i+0]; t1 = pointValueTextureCoords[index1+0]; tc[i] = osp::vec2f{t1,0}; int index2 = indexArray[i+1]; t2 = pointValueTextureCoords[index2+0]; tc[i+1] = osp::vec2f{t2,0}; } OSPData tcs = ospNewData(indexArray.size(), OSP_FLOAT2, &tc[0]); ospSetData(ospMesh, "texcoord", tcs); ospSetData(ospMesh, "vertex.texcoord", tcs); } else if (numTextureCoordinates) { //2d texture mapping float *itc = textureCoordinates; tc = new osp::vec2f[indexArray.size()]; for (size_t i = 0; i < indexArray.size(); i+=2) { float t1,t2; int index1 = indexArray[i+0]; t1 = itc[index1*2+0]; t2 = itc[index1*2+1]; tc[i] = osp::vec2f{t1,t2}; int index2 = indexArray[i+1]; t1 = itc[index2*2+0]; t2 = itc[index2*2+1]; tc[i+1] = osp::vec2f{t1,t2}; } OSPData tcs = ospNewData(indexArray.size(), OSP_FLOAT2, &tc[0]); ospSetData(ospMesh, "texcoord", tcs); } } delete[] tc; if (useCustomMaterial) { ospSetMaterial(ospMesh, actorMaterial); } else if (vColorTextureMap && _hastm) { osp::Texture2D *t2d = vtkOSPRayMaterialHelpers::VTKToOSPTexture(vColorTextureMap); OSPMaterial ospMaterial = ospNewMaterial(oRenderer,"OBJMaterial"); ospSetObject(ospMaterial, "map_Kd", ((OSPTexture2D)(t2d))); ospCommit(t2d); ospCommit(ospMaterial); ospSetMaterial(ospMesh, ospMaterial); } else if (numCellMaterials) { //per cell color ospSet1i(ospMesh, "offset_materialID", 6*sizeof(float)); ospSetData(ospMesh, "materialList", CellMaterials); } else if (numPointColors) { //per point color ospSet1i(ospMesh, "offset_colorID", 6*sizeof(float)); ospSetData(ospMesh, "color", _PointColors); } else { //per actor color ospSetMaterial(ospMesh, actorMaterial); } ospAddGeometry(oModel, ospMesh); ospCommit(ospMesh); ospRelease(_PointColors); ospRelease(_mdata); delete[] mdata; return ospMesh; } //---------------------------------------------------------------------------- OSPGeometry RenderAsTriangles(OSPData vertices, std::vector &indexArray, std::vector &rIndexArray, bool useCustomMaterial, OSPMaterial actorMaterial, int numNormals, osp::vec3f *normals, vtkImageData *vColorTextureMap, int numTextureCoordinates, float *textureCoordinates, int numCellMaterials, OSPData CellMaterials, int numPointColors, osp::vec4f *PointColors, int numPointValueTextureCoords, float *pointValueTextureCoords, OSPModel oModel, OSPRenderer oRenderer ) { OSPGeometry ospMesh = ospNewGeometry("trianglemesh"); ospSetData(ospMesh, "position", vertices); size_t numTriangles = indexArray.size() / 3; osp::vec3i *triangles = new osp::vec3i[numTriangles]; for (size_t i = 0, mi = 0; i < numTriangles; i++, mi += 3) { triangles[i] = osp::vec3i{static_cast(indexArray[mi + 0]), static_cast(indexArray[mi + 1]), static_cast(indexArray[mi + 2])}; } OSPData index = ospNewData(numTriangles, OSP_INT3, &triangles[0]); delete[] triangles; ospSetData(ospMesh, "index", index); OSPData _normals = nullptr; if (numNormals) { _normals = ospNewData(numNormals, OSP_FLOAT3, &normals[0]); ospSetData(ospMesh, "vertex.normal", _normals); } //send the texture map and texture coordinates over bool _hastm = false; osp::vec2f *tc = nullptr; if (numTextureCoordinates || numPointValueTextureCoords) { _hastm = true; if (numPointValueTextureCoords) { //using 1D texture for point value LUT tc = new osp::vec2f[numPointValueTextureCoords]; for (size_t i = 0; i < static_cast(numPointValueTextureCoords); i++) { tc[i] = osp::vec2f{pointValueTextureCoords[i],0}; } OSPData tcs = ospNewData(numPointValueTextureCoords, OSP_FLOAT2, &tc[0]); ospSetData(ospMesh, "vertex.texcoord", tcs); } else if (numTextureCoordinates) { //2d texture mapping tc = new osp::vec2f[numTextureCoordinates/2]; float *itc = textureCoordinates; for (size_t i = 0; i < static_cast(numTextureCoordinates); i+=2) { float t1,t2; t1 = *itc; itc++; t2 = *itc; itc++; tc[i/2] = osp::vec2f{t1,t2}; } OSPData tcs = ospNewData(numTextureCoordinates/2, OSP_FLOAT2, &tc[0]); ospSetData(ospMesh, "vertex.texcoord", tcs); } } delete[] tc; //send over cell colors, point colors or whole actor color OSPData _cmats = nullptr; OSPData _PointColors = nullptr; int *ids = nullptr; if (useCustomMaterial) { ospSetMaterial(ospMesh, actorMaterial); } else if (vColorTextureMap && _hastm) { osp::Texture2D *t2d = vtkOSPRayMaterialHelpers::VTKToOSPTexture(vColorTextureMap); OSPMaterial ospMaterial = ospNewMaterial(oRenderer,"OBJMaterial"); ospSetObject(ospMaterial, "map_Kd", ((OSPTexture2D)(t2d))); ospCommit(t2d); ospCommit(ospMaterial); ospSetMaterial(ospMesh, ospMaterial); } else if (numCellMaterials) { ids = new int[numTriangles]; for (size_t i = 0; i < numTriangles; i++) { ids[i] = rIndexArray[i*3+0]; } _cmats = ospNewData(numTriangles, OSP_INT, &ids[0]); ospSetData(ospMesh, "prim.materialID", _cmats); ospSetData(ospMesh, "materialList", CellMaterials); } else if (numPointColors) { _PointColors = ospNewData(numPointColors, OSP_FLOAT4, &PointColors[0]); ospSetData(ospMesh, "vertex.color", _PointColors); } else { ospSetMaterial(ospMesh, actorMaterial); } ospAddGeometry(oModel, ospMesh); ospCommit(ospMesh); ospRelease(index); ospRelease(_normals); ospRelease(_PointColors); ospRelease(_cmats); delete[] ids; return ospMesh; } //------------------------------------------------------------------------------ OSPMaterial MakeActorMaterial(vtkOSPRayRendererNode *orn, OSPRenderer oRenderer, vtkProperty *property, double *ambientColor, double *diffuseColor, float *specularf, double opacity, bool pt_avail, bool &useCustomMaterial, std::map &mats, const std::string& materialName) { useCustomMaterial = false; OSPMaterial oMaterial; if (pt_avail && property->GetMaterialName()) { if (std::string("Value Indexed") == property->GetMaterialName()) { oMaterial = ospNewMaterial(oRenderer, "OBJMaterial"); vtkOSPRayMaterialHelpers::MakeMaterials(orn, oRenderer, mats); std::string requested_mat_name = materialName; if (requested_mat_name != "" && requested_mat_name != "Value Indexed") { oMaterial = vtkOSPRayMaterialHelpers::MakeMaterial (orn, oRenderer, requested_mat_name.c_str()); useCustomMaterial = true; } } else { oMaterial = vtkOSPRayMaterialHelpers::MakeMaterial (orn, oRenderer, property->GetMaterialName()); useCustomMaterial = true; } } else { oMaterial = ospNewMaterial(oRenderer, "OBJMaterial"); } float lum = static_cast(vtkOSPRayActorNode::GetLuminosity(property)); float ambientf[] = { static_cast(ambientColor[0]*property->GetAmbient()), static_cast(ambientColor[1]*property->GetAmbient()), static_cast(ambientColor[2]*property->GetAmbient()) }; float diffusef[] = { static_cast(diffuseColor[0]*property->GetDiffuse()), static_cast(diffuseColor[1]*property->GetDiffuse()), static_cast(diffuseColor[2]*property->GetDiffuse()) }; if (lum>0.0) { oMaterial = ospNewMaterial(oRenderer, "Luminous"); ospSet3fv(oMaterial, "color", diffusef); ospSetf(oMaterial, "intensity", lum); } float specPower = static_cast(property->GetSpecularPower()); float specAdjust = 2.0f/(2.0f+specPower); specularf[0] = static_cast(property->GetSpecularColor()[0]* property->GetSpecular()* specAdjust); specularf[1] = static_cast(property->GetSpecularColor()[1]* property->GetSpecular()* specAdjust); specularf[2] = static_cast(property->GetSpecularColor()[2]* property->GetSpecular()* specAdjust); if (!useCustomMaterial) { ospSet3fv(oMaterial,"Ka",ambientf); if (property->GetDiffuse()==0.0) { //a workaround for ParaView, remove when ospray supports Ka ospSet3fv(oMaterial,"Kd",ambientf); } else { ospSet3fv(oMaterial,"Kd",diffusef); } ospSet3fv(oMaterial,"Ks",specularf); ospSet1f(oMaterial,"Ns",specPower); ospSet1f(oMaterial,"d",float(opacity)); } return oMaterial; } //------------------------------------------------------------------------------ OSPMaterial MakeActorMaterial(vtkOSPRayRendererNode *orn, OSPRenderer oRenderer, vtkProperty *property, double *ambientColor, double *diffuseColor, float *specularf, double opacity) { bool dontcare1; std::map dontcare2; return MakeActorMaterial(orn, oRenderer, property, ambientColor, diffuseColor, specularf, opacity, false, dontcare1, dontcare2, ""); }; } //============================================================================ vtkStandardNewMacro(vtkOSPRayPolyDataMapperNode); //---------------------------------------------------------------------------- vtkOSPRayPolyDataMapperNode::vtkOSPRayPolyDataMapperNode() { this->OSPMeshes = nullptr; } //---------------------------------------------------------------------------- vtkOSPRayPolyDataMapperNode::~vtkOSPRayPolyDataMapperNode() { delete (vtkosp::MyGeom*)this->OSPMeshes; } //---------------------------------------------------------------------------- void vtkOSPRayPolyDataMapperNode::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); } //---------------------------------------------------------------------------- void vtkOSPRayPolyDataMapperNode::ORenderPoly( void *renderer, void *model, vtkOSPRayActorNode *aNode, vtkPolyData * poly, double *ambientColor, double *diffuseColor, double opacity, std::string materialName) { //todo: this is ugly { vtkOSPRayRendererNode *orn = static_cast( this->GetFirstAncestorOfType("vtkOSPRayRendererNode")); OSPRenderer oRenderer = static_cast(renderer); OSPModel oModel = static_cast(model); vtkActor *act = vtkActor::SafeDownCast(aNode->GetRenderable()); vtkProperty *property = act->GetProperty(); vtkosp::MyGeom *myMeshes = (vtkosp::MyGeom*)this->OSPMeshes; //make geometry std::vector _vertices; vtkPolyDataMapperNode::TransformPoints(act, poly, _vertices); size_t numPositions = _vertices.size()/3; osp::vec3fa *vertices = new osp::vec3fa[numPositions]; for (size_t i = 0; i < numPositions; i++) { vertices[i] = osp::vec3fa{static_cast(_vertices[i*3+0]), static_cast(_vertices[i*3+1]), static_cast(_vertices[i*3+2])}; } OSPData position = ospNewData(numPositions, OSP_FLOAT3A, &vertices[0]); ospCommit(position); _vertices.clear(); //make connectivity vtkPolyDataMapperNode::vtkPDConnectivity conn; vtkPolyDataMapperNode::MakeConnectivity(poly, property->GetRepresentation(), conn); //choosing sphere and cylinder radii (for points and lines) that //approximate pointsize and linewidth vtkMapper *mapper = act->GetMapper(); double length = 1.0; if (mapper) { length = mapper->GetLength(); } double pointSize = length/1000.0 * property->GetPointSize(); double lineWidth = length/1000.0 * property->GetLineWidth(); //finer control over sphere and cylinders sizes int enable_scaling = vtkOSPRayActorNode::GetEnableScaling(act); vtkDataArray *scaleArray = nullptr; vtkPiecewiseFunction *scaleFunction = nullptr; if (enable_scaling && mapper) { vtkInformation *mapInfo = mapper->GetInformation(); char *scaleArrayName = (char *)mapInfo->Get (vtkOSPRayActorNode::SCALE_ARRAY_NAME()); scaleArray = poly->GetPointData()->GetArray(scaleArrayName); scaleFunction = vtkPiecewiseFunction::SafeDownCast (mapInfo->Get(vtkOSPRayActorNode::SCALE_FUNCTION())); } //per actor material float specularf[3]; bool useCustomMaterial = false; std::map mats; bool pt_avail = orn->GetRendererType( vtkRenderer::SafeDownCast(orn->GetRenderable())) == std::string("pathtracer"); //} OSPMaterial oMaterial = vtkosp::MakeActorMaterial(orn, oRenderer, property, ambientColor, diffuseColor, specularf, opacity, pt_avail, useCustomMaterial, mats, materialName ); ospCommit(oMaterial); //texture int numTextureCoordinates = 0; float *textureCoordinates = nullptr; if (vtkDataArray *da = poly->GetPointData()->GetTCoords()) { numTextureCoordinates = da->GetNumberOfTuples(); textureCoordinates = new float[numTextureCoordinates*2]; float *tp = textureCoordinates; for (int i=0; i(da->GetTuple(i)[0]); tp++; *tp = static_cast(da->GetTuple(i)[1]); tp++; } numTextureCoordinates = numTextureCoordinates*2; } vtkTexture *texture = act->GetTexture(); vtkImageData* vColorTextureMap = nullptr; if (texture) { vColorTextureMap = vtkImageData::SafeDownCast (texture->GetInput()); } //colors from point and cell arrays int numCellMaterials = 0; OSPData cellMaterials = nullptr; int numPointColors = 0; osp::vec4f *pointColors = nullptr; int numPointValueTextureCoords = 0; float *pointValueTextureCoords = nullptr; // //now ask mapper to do most of the work and provide use with //colors per cell and colors or texture coordinates per point vtkUnsignedCharArray *vColors = nullptr; vtkFloatArray *vColorCoordinates = nullptr; vtkImageData* pColorTextureMap = nullptr; int cellFlag = -1; //mapper tells us which if (mapper) { mapper->MapScalars(poly, 1.0, cellFlag); vColors = mapper->GetColorMapColors(); vColorCoordinates = mapper->GetColorCoordinates(); pColorTextureMap = mapper->GetColorTextureMap(); } if (vColors) { if (cellFlag==2 && mapper->GetFieldDataTupleId() > -1) { //color comes from field data entry bool use_material = false; //check if the field data content says to use a material lookup vtkScalarsToColors *s2c = mapper->GetLookupTable(); bool try_mats = s2c->GetIndexedLookup() && s2c->GetNumberOfAnnotatedValues() && mats.size()>0; if (try_mats) { int cflag2 =-1; vtkAbstractArray *scalars = mapper->GetAbstractScalars (poly, mapper->GetScalarMode(), mapper->GetArrayAccessMode(), mapper->GetArrayId(), mapper->GetArrayName(), cflag2); vtkVariant v = scalars->GetVariantValue(mapper->GetFieldDataTupleId()); vtkIdType idx = s2c->GetAnnotatedValueIndex(v); if (idx > -1) { std::string name(s2c->GetAnnotation(idx)); if (mats.find(name) != mats.end()) { //yes it does! oMaterial = mats[name]; ospCommit(oMaterial); use_material = true; } } } if (!use_material) { //just use the color for the field data value int numComp = vColors->GetNumberOfComponents(); unsigned char *colorPtr = vColors->GetPointer(0); colorPtr = colorPtr + mapper->GetFieldDataTupleId()*numComp; // this setting (and all the other scalar colors) // really depends on mapper->ScalarMaterialMode // but I'm not sure Ka is working currently so leaving it on Kd float fdiffusef[] = { static_cast(colorPtr[0]*property->GetDiffuse()/255.0f), static_cast(colorPtr[1]*property->GetDiffuse()/255.0f), static_cast(colorPtr[2]*property->GetDiffuse()/255.0f) }; ospSet3fv(oMaterial,"Kd",fdiffusef); ospCommit(oMaterial); } } else if (cellFlag==1) { //color or material on cell vtkScalarsToColors *s2c = mapper->GetLookupTable(); std::vector cellColors; vtkosp::CellMaterials(poly, mapper, s2c, mats, oRenderer, cellColors, vColors, specularf, float(property->GetSpecularPower()), opacity); numCellMaterials = static_cast(cellColors.size()); cellMaterials = ospNewData(cellColors.size(), OSP_OBJECT, &cellColors[0]); ospCommit(cellMaterials); cellColors.clear(); } else if (cellFlag==0) { //color on point interpolated RGB numPointColors = vColors->GetNumberOfTuples(); pointColors = new osp::vec4f[numPointColors]; for (int i = 0; i < numPointColors; i++) { unsigned char *color = vColors->GetPointer(4 * i); pointColors[i] = osp::vec4f{color[0] / 255.0f, color[1] / 255.0f, color[2] / 255.0f, 1.f}; } } } else { if (vColorCoordinates && pColorTextureMap) { //color on point interpolated values (subsequently colormapped via 1D LUT) numPointValueTextureCoords = vColorCoordinates->GetNumberOfTuples(); pointValueTextureCoords = new float[numPointValueTextureCoords]; float *tc = vColorCoordinates->GetPointer(0); for (int i = 0; i < numPointValueTextureCoords; i++) { pointValueTextureCoords[i] = *tc; tc+=2; } vColorTextureMap = pColorTextureMap; } } //create an ospray mesh for the vertex cells if (conn.vertex_index.size()) { myMeshes ->Add(vtkosp::RenderAsSpheres(vertices, conn.vertex_index, conn.vertex_reverse, pointSize, scaleArray, scaleFunction, useCustomMaterial, oMaterial, vColorTextureMap, numTextureCoordinates, textureCoordinates, numCellMaterials, cellMaterials, numPointColors, pointColors, numPointValueTextureCoords, pointValueTextureCoords, oModel, oRenderer )); } //create an ospray mesh for the line cells if (conn.line_index.size()) { //format depends on representation style if (property->GetRepresentation() == VTK_POINTS) { myMeshes ->Add(vtkosp::RenderAsSpheres(vertices, conn.line_index, conn.line_reverse, pointSize, scaleArray, scaleFunction, useCustomMaterial, oMaterial, vColorTextureMap, numTextureCoordinates, textureCoordinates, numCellMaterials, cellMaterials, numPointColors, pointColors, numPointValueTextureCoords, pointValueTextureCoords, oModel, oRenderer )); } else { myMeshes ->Add(vtkosp::RenderAsCylinders(vertices, conn.line_index, conn.line_reverse, lineWidth, scaleArray, scaleFunction, useCustomMaterial, oMaterial, vColorTextureMap, numTextureCoordinates, textureCoordinates, numCellMaterials, cellMaterials, numPointColors, pointColors, numPointValueTextureCoords, pointValueTextureCoords, oModel, oRenderer )); } } //create an ospray mesh for the polygon cells if (conn.triangle_index.size()) { //format depends on representation style switch (property->GetRepresentation()) { case VTK_POINTS: { myMeshes ->Add(vtkosp::RenderAsSpheres(vertices, conn.triangle_index, conn.triangle_reverse, pointSize, scaleArray, scaleFunction, useCustomMaterial, oMaterial, vColorTextureMap, numTextureCoordinates, textureCoordinates, numCellMaterials, cellMaterials, numPointColors, pointColors, numPointValueTextureCoords, pointValueTextureCoords, oModel, oRenderer )); break; } case VTK_WIREFRAME: { myMeshes ->Add(vtkosp::RenderAsCylinders(vertices, conn.triangle_index, conn.triangle_reverse, lineWidth, scaleArray, scaleFunction, useCustomMaterial, oMaterial, vColorTextureMap, numTextureCoordinates, textureCoordinates, numCellMaterials, cellMaterials, numPointColors, pointColors, numPointValueTextureCoords, pointValueTextureCoords, oModel, oRenderer )); break; } default: { if (property->GetEdgeVisibility()) { //edge mesh vtkPolyDataMapperNode::vtkPDConnectivity conn2; vtkPolyDataMapperNode::MakeConnectivity(poly, VTK_WIREFRAME, conn2); //edge material double *eColor = property->GetEdgeColor(); OSPMaterial oMaterial2 = vtkosp::MakeActorMaterial(orn, oRenderer, property, eColor, eColor, specularf, opacity); ospCommit(oMaterial2); myMeshes ->Add(vtkosp::RenderAsCylinders(vertices, conn2.triangle_index, conn2.triangle_reverse, lineWidth, scaleArray, scaleFunction, false, oMaterial2, vColorTextureMap, 0, textureCoordinates, numCellMaterials, cellMaterials, numPointColors, pointColors, 0, pointValueTextureCoords, oModel, oRenderer )); } osp::vec3f *normals = nullptr; int numNormals = 0; if (property->GetInterpolation() != VTK_FLAT) { vtkDataArray *vNormals = poly->GetPointData()->GetNormals(); if (vNormals) { vtkosp::VToOPointNormals (vNormals, normals); numNormals = vNormals->GetNumberOfTuples(); } } myMeshes ->Add(vtkosp::RenderAsTriangles(position, conn.triangle_index, conn.triangle_reverse, useCustomMaterial, oMaterial, numNormals, normals, vColorTextureMap, numTextureCoordinates, textureCoordinates, numCellMaterials, cellMaterials, numPointColors, pointColors, numPointValueTextureCoords, pointValueTextureCoords, oModel, oRenderer )); delete[] normals; } } } if (conn.strip_index.size()) { switch (property->GetRepresentation()) { case VTK_POINTS: { myMeshes ->Add(vtkosp::RenderAsSpheres(vertices, conn.strip_index, conn.strip_reverse, pointSize, scaleArray, scaleFunction, useCustomMaterial, oMaterial, vColorTextureMap, numTextureCoordinates, textureCoordinates, numCellMaterials, cellMaterials, numPointColors, pointColors, numPointValueTextureCoords, pointValueTextureCoords, oModel, oRenderer )); break; } case VTK_WIREFRAME: { myMeshes ->Add(vtkosp::RenderAsCylinders(vertices, conn.strip_index, conn.strip_reverse, lineWidth, scaleArray, scaleFunction, useCustomMaterial, oMaterial, vColorTextureMap, numTextureCoordinates, textureCoordinates, numCellMaterials, cellMaterials, numPointColors, pointColors, numPointValueTextureCoords, pointValueTextureCoords, oModel, oRenderer )); break; } default: { if (property->GetEdgeVisibility()) { //edge mesh vtkPolyDataMapperNode::vtkPDConnectivity conn2; vtkPolyDataMapperNode::MakeConnectivity(poly, VTK_WIREFRAME, conn2); //edge material double *eColor = property->GetEdgeColor(); OSPMaterial oMaterial2 = vtkosp::MakeActorMaterial(orn, oRenderer, property, eColor, eColor, specularf, opacity); ospCommit(oMaterial2); myMeshes ->Add(vtkosp::RenderAsCylinders(vertices, conn2.strip_index, conn2.strip_reverse, lineWidth, scaleArray, scaleFunction, false, oMaterial2, vColorTextureMap, 0, textureCoordinates, numCellMaterials, cellMaterials, numPointColors, pointColors, 0, pointValueTextureCoords, oModel, oRenderer )); } osp::vec3f *normals = nullptr; int numNormals = 0; if (property->GetInterpolation() != VTK_FLAT) { vtkDataArray *vNormals = poly->GetPointData()->GetNormals(); if (vNormals) { vtkosp::VToOPointNormals (vNormals, normals); numNormals = vNormals->GetNumberOfTuples(); } } myMeshes ->Add(vtkosp::RenderAsTriangles(position, conn.strip_index, conn.strip_reverse, useCustomMaterial, oMaterial, numNormals, normals, vColorTextureMap, numTextureCoordinates, textureCoordinates, numCellMaterials, cellMaterials, numPointColors, pointColors, numPointValueTextureCoords, pointValueTextureCoords, oModel, oRenderer )); delete[] normals; } } } ospRelease(position); delete[] vertices; delete[] pointColors; delete[] pointValueTextureCoords; delete[] textureCoordinates; } void vtkOSPRayPolyDataMapperNode::AddMeshesToModel(void *arg) { vtkosp::MyGeom *myMeshes = (vtkosp::MyGeom*)this->OSPMeshes; OSPModel oModel = static_cast(arg); myMeshes->AddMyselfTo(oModel); } void vtkOSPRayPolyDataMapperNode::CreateNewMeshes() { vtkosp::MyGeom *myMeshes = (vtkosp::MyGeom*)this->OSPMeshes; delete myMeshes; myMeshes = new vtkosp::MyGeom(); this->OSPMeshes = myMeshes; } //---------------------------------------------------------------------------- void vtkOSPRayPolyDataMapperNode::Invalidate(bool prepass) { if (prepass) { this->RenderTime = 0; } } //---------------------------------------------------------------------------- void vtkOSPRayPolyDataMapperNode::Render(bool prepass) { if (prepass) { // we use a lot of params from our parent vtkOSPRayActorNode *aNode = vtkOSPRayActorNode::SafeDownCast(this->Parent); vtkActor *act = vtkActor::SafeDownCast(aNode->GetRenderable()); if (act->GetVisibility() == false) { delete (vtkosp::MyGeom*)this->OSPMeshes; this->OSPMeshes = nullptr; return; } vtkOSPRayRendererNode *orn = static_cast( this->GetFirstAncestorOfType("vtkOSPRayRendererNode")); //if there are no changes, just reuse last result bool enable_cache = true; //turn off to force rebuilds for debugging vtkMTimeType inTime = aNode->GetMTime(); if (enable_cache && this->RenderTime >= inTime) { OSPModel oModel = static_cast(orn->GetOModel()); this->AddMeshesToModel(oModel); return; } this->RenderTime = inTime; //something changed so make new meshes this->CreateNewMeshes(); vtkPolyData *poly = nullptr; vtkMapper *mapper = act->GetMapper(); if (mapper) { poly = (vtkPolyData*)(mapper->GetInput()); } if (poly) { vtkProperty * property = act->GetProperty(); this->ORenderPoly( orn->GetORenderer(), orn->GetOModel(), aNode, poly, property->GetAmbientColor(), property->GetDiffuseColor(), property->GetOpacity(), "" ); } } }