void VolumeViewer::setIsovalues(std::vector<float> isovalues) { OSPData isovaluesData = ospNewData(isovalues.size(), OSP_FLOAT, &isovalues[0]); // Remove existing isosurface geometries from models. for(size_t i=0; i<modelStates.size(); i++) { for(size_t j=0; j<modelStates[i].isosurfaces.size(); j++) ospRemoveGeometry(modelStates[i].model, modelStates[i].isosurfaces[j]); modelStates[i].isosurfaces.clear(); } // Add new isosurfaces for each volume of each model. Later we can do this only for the active model on time step change... for(size_t i=0; i<modelStates.size(); i++) { if(isovalues.size() > 0) { for(size_t j=0; j<modelStates[i].volumes.size(); j++) { OSPGeometry isosurfacesGeometry = ospNewGeometry("isosurfaces"); ospSetData(isosurfacesGeometry, "isovalues", isovaluesData); ospSetObject(isosurfacesGeometry, "volume", modelStates[i].volumes[j]); ospCommit(isosurfacesGeometry); ospAddGeometry(modelStates[i].model, isosurfacesGeometry); modelStates[i].isosurfaces.push_back(isosurfacesGeometry); } } ospCommit(modelStates[i].model); } render(); }
void Geometry::preCommit(RenderContext &) { auto ospGeometry = valueAs<OSPGeometry>(); if (!ospGeometry) { auto type = child("type").valueAs<std::string>(); ospGeometry = ospNewGeometry(type.c_str()); setValue(ospGeometry); child("bounds") = computeBounds(); } }
void VolumeViewer::addGeometry(std::string filename) { // For now we assume PLY geometry files. Later we can support other geometry formats. // Get filename if not specified. if(filename.empty()) filename = QFileDialog::getOpenFileName(this, tr("Load geometry"), ".", "Geometry files (*.ply *.dds)").toStdString(); if(filename.empty()) return; // Attempt to load the geometry through the TriangleMeshFile loader. OSPGeometry triangleMesh = ospNewGeometry("trianglemesh"); // If successful, commit the triangle mesh and add it to all models. if(TriangleMeshFile::importTriangleMesh(filename, triangleMesh) != NULL) { // For now: if this is a DDS geometry, assume it is a horizon and its color should be mapped through the first volume's transfer function. if(QString(filename.c_str()).endsWith(".dds") && modelStates.size() > 0 && modelStates[0].volumes.size() > 0) { OSPMaterial material = ospNewMaterial(renderer, "default"); ospSet3f(material, "Kd", 1,1,1); ospSetObject(material, "volume", modelStates[0].volumes[0]); ospCommit(material); ospSetMaterial(triangleMesh, material); } ospCommit(triangleMesh); // Create an instance of the geometry and add the instance to the main model(s)--this prevents the geometry // from being rebuilt every time the main model is committed (e.g. when slices / isosurfaces are manipulated) OSPModel modelInstance = ospNewModel(); ospAddGeometry(modelInstance, triangleMesh); ospCommit(modelInstance); ospcommon::affine3f xfm = ospcommon::one; OSPGeometry triangleMeshInstance = ospNewInstance(modelInstance, (osp::affine3f&)xfm); ospCommit(triangleMeshInstance); for(size_t i=0; i<modelStates.size(); i++) { ospAddGeometry(modelStates[i].model, triangleMeshInstance); ospCommit(modelStates[i].model); } // Force render. render(); } }
OSPGeometry OSPObjectFile::importTriangleMesh(const tinyxml2::XMLNode *root) { // Create the OSPRay object. OSPGeometry triangleMesh = ospNewGeometry("trianglemesh"); // Temporary storage for the file name attribute if specified. const char *triangleMeshFilename = NULL; // Iterate over object attributes. for (const tinyxml2::XMLNode *node = root->FirstChild() ; node ; node = node->NextSibling()) { // File containing a triangle mesh specification and / or data. if (!strcmp(node->ToElement()->Name(), "filename")) { triangleMeshFilename = node->ToElement()->GetText(); continue; } // Scaling for vertex coordinates. if (!strcmp(node->ToElement()->Name(), "scale")) { importAttributeFloat3(node, triangleMesh); continue; } // Error check. exitOnCondition(true, "unrecognized XML element type '" + std::string(node->ToElement()->Name()) + "'"); } // Load the contents of the triangle mesh file if specified. if (triangleMeshFilename != NULL) { // Some implementations of 'dirname()' are destructive. char *duplicateFilename = strdup(filename.c_str()); // The triangle mesh file path is absolute. if (triangleMeshFilename[0] == '/') { return(TriangleMeshFile::importTriangleMesh(triangleMeshFilename, triangleMesh)); } // The triangle mesh file path is relative to the object file path. if (triangleMeshFilename[0] != '/') { return(TriangleMeshFile::importTriangleMesh((std::string(dirname(duplicateFilename)) + "/" + triangleMeshFilename).c_str(), triangleMesh)); } // Free the temporary character array. if (duplicateFilename != NULL) free(duplicateFilename); } // The populated triangle mesh object. return triangleMesh; }
void VolumeViewer::setSlices(std::vector<SliceParameters> sliceParameters) { // Provide the slices to OSPRay as the coefficients (a,b,c,d) of the plane equation ax + by + cz + d = 0. std::vector<ospcommon::vec4f> planes; for(size_t i=0; i<sliceParameters.size(); i++) planes.push_back(ospcommon::vec4f(sliceParameters[i].normal.x, sliceParameters[i].normal.y, sliceParameters[i].normal.z, -dot(sliceParameters[i].origin, sliceParameters[i].normal))); OSPData planesData = ospNewData(planes.size(), OSP_FLOAT4, &planes[0].x); // Remove existing slice geometries from models. for(size_t i=0; i<modelStates.size(); i++) { for(size_t j=0; j<modelStates[i].slices.size(); j++) ospRemoveGeometry(modelStates[i].model, modelStates[i].slices[j]); modelStates[i].slices.clear(); } // Add new slices for each volume of each model. Later we can do this only for the active model on time step change... for(size_t i=0; i<modelStates.size(); i++) { if(planes.size() > 0) { for(size_t j=0; j<modelStates[i].volumes.size(); j++) { OSPGeometry slicesGeometry = ospNewGeometry("slices"); ospSetData(slicesGeometry, "planes", planesData); ospSetObject(slicesGeometry, "volume", modelStates[i].volumes[j]); ospCommit(slicesGeometry); ospAddGeometry(modelStates[i].model, slicesGeometry); modelStates[i].slices.push_back(slicesGeometry); } } ospCommit(modelStates[i].model); } render(); }
int main(int ac, const char **av) { // image size osp_vec2i imgSize; imgSize.x = 1024; // width imgSize.y = 768; // height // camera float cam_pos[] = {0.f, 0.f, 0.f}; float cam_up [] = {0.f, 1.f, 0.f}; float cam_view [] = {0.1f, 0.f, 1.f}; // triangle mesh data float vertex[] = { -1.0f, -1.0f, 3.0f, 0.f, -1.0f, 1.0f, 3.0f, 0.f, 1.0f, -1.0f, 3.0f, 0.f, 0.1f, 0.1f, 0.3f, 0.f }; float color[] = { 0.9f, 0.5f, 0.5f, 1.0f, 0.8f, 0.8f, 0.8f, 1.0f, 0.8f, 0.8f, 0.8f, 1.0f, 0.5f, 0.9f, 0.5f, 1.0f }; int32_t index[] = { 0, 1, 2, 1, 2, 3 }; // initialize OSPRay; OSPRay parses (and removes) its commandline parameters, e.g. "--osp:debug" ospInit(&ac, av); // create and setup camera OSPCamera camera = ospNewCamera("perspective"); ospSetf(camera, "aspect", imgSize.x/(float)imgSize.y); ospSet3fv(camera, "pos", cam_pos); ospSet3fv(camera, "dir", cam_view); ospSet3fv(camera, "up", cam_up); ospCommit(camera); // commit each object to indicate modifications are done // create and setup model and mesh OSPGeometry mesh = ospNewGeometry("triangles"); OSPData data = ospNewData(4, OSP_FLOAT3A, vertex, 0); // OSP_FLOAT3 format is also supported for vertex positions (currently not on MIC) ospCommit(data); ospSetData(mesh, "vertex", data); data = ospNewData(4, OSP_FLOAT4, color, 0); ospCommit(data); ospSetData(mesh, "vertex.color", data); data = ospNewData(2, OSP_INT3, index, 0); // OSP_INT4 format is also supported for triangle indices ospCommit(data); ospSetData(mesh, "index", data); ospCommit(mesh); OSPModel world = ospNewModel(); ospAddGeometry(world, mesh); ospCommit(world); // create and setup renderer OSPRenderer renderer = ospNewRenderer("scivis"); // choose Scientific Visualization renderer ospSet1f(renderer, "aoWeight", 1.0f); // with full Ambient Occlusion ospSet1i(renderer, "aoSamples", 1); ospSetObject(renderer, "model", world); ospSetObject(renderer, "camera", camera); ospCommit(renderer); // create and setup framebuffer OSPFrameBuffer framebuffer = ospNewFrameBuffer(&imgSize, OSP_FB_SRGBA, OSP_FB_COLOR | /*OSP_FB_DEPTH |*/ OSP_FB_ACCUM); ospFrameBufferClear(framebuffer, OSP_FB_COLOR | OSP_FB_ACCUM); // render one frame ospRenderFrame(framebuffer, renderer, OSP_FB_COLOR | OSP_FB_ACCUM); // access framebuffer and write its content as PPM file const uint32_t * fb = (uint32_t*)ospMapFrameBuffer(framebuffer, OSP_FB_COLOR); writePPM("firstFrameC.ppm", &imgSize, fb); ospUnmapFrameBuffer(fb, framebuffer); // render 10 more frames, which are accumulated to result in a better converged image for (int frames = 0; frames < 10; frames++) ospRenderFrame(framebuffer, renderer, OSP_FB_COLOR | OSP_FB_ACCUM); fb = (uint32_t*)ospMapFrameBuffer(framebuffer, OSP_FB_COLOR); writePPM("accumulatedFrameC.ppm", &imgSize, fb); ospUnmapFrameBuffer(fb, framebuffer); return 0; }