示例#1
0
  void StructuredVolume::getVolumeFromMemory() 
  {
    //! Create the equivalent ISPC volume container and allocate memory for voxel data.
    createEquivalentISPC();

    //! Get a pointer to the source voxel data.
    const Data *voxelData = getParamData("voxelData", NULL);  
    exitOnCondition(voxelData == NULL, "no voxel data specified");  

    const uint8 *data = (const uint8 *) voxelData->data;

    //! The dimensions of the source voxel data and target volume must match.
    exitOnCondition(size_t(volumeDimensions.x) * volumeDimensions.y * volumeDimensions.z != voxelData->numItems, "unexpected source voxel data dimensions");

    //! The source and target voxel types must match.
    exitOnCondition(getVoxelType() != voxelData->type, "unexpected source voxel type");

    //! Size of a volume slice in bytes.
    size_t sliceSizeInBytes = volumeDimensions.x * volumeDimensions.y * getVoxelSizeInBytes();

    //! Copy voxel data into the volume in slices to avoid overflow in ISPC offset calculations.
    for (size_t z=0 ; z < volumeDimensions.z ; z++) 
      setRegion(&data[z * sliceSizeInBytes], vec3i(0, 0, z), 
                vec3i(volumeDimensions.x, volumeDimensions.y, 1));

  }
  void LinearTransferFunction::createEquivalentISPC()
  {
    // The equivalent ISPC transfer function must not exist yet.
    exitOnCondition(ispcEquivalent != NULL, "attempt to overwrite an existing ISPC transfer function");

    // Create the equivalent ISPC transfer function.
    ispcEquivalent = ispc::LinearTransferFunction_createInstance();

    // The object may not have been created.
    exitOnCondition(ispcEquivalent == NULL, "unable to create ISPC transfer function");
  }
示例#3
0
void VolumeViewer::initObjects(const std::string &renderer_type)
{
  // Create an OSPRay renderer.
  renderer = ospNewRenderer(renderer_type.c_str());
  exitOnCondition(renderer == NULL, "could not create OSPRay renderer object");

  // Set renderer defaults (if not using 'aoX' renderers)
  if (renderer_type[0] != 'a' && renderer_type[1] != 'o')
  {
    ospSet1i(renderer, "aoSamples", 1);
    ospSet1i(renderer, "shadowsEnabled", 1);
  }

  // Create OSPRay ambient and directional lights. GUI elements will modify their parameters.
  ambientLight = ospNewLight(renderer, "AmbientLight");
  exitOnCondition(ambientLight == NULL, "could not create ambient light");
  ospCommit(ambientLight);

  directionalLight = ospNewLight(renderer, "DirectionalLight");
  exitOnCondition(directionalLight == NULL, "could not create directional light");
  ospCommit(directionalLight);

  // Set the light sources on the renderer.
  std::vector<OSPLight> lights;
  lights.push_back(ambientLight);
  lights.push_back(directionalLight);

  ospSetData(renderer, "lights", ospNewData(lights.size(), OSP_OBJECT, &lights[0]));

  // Create an OSPRay transfer function.
  transferFunction = ospNewTransferFunction("piecewise_linear");
  exitOnCondition(transferFunction == NULL, "could not create OSPRay transfer function object");
  ospCommit(transferFunction);

  // Load OSPRay objects from files.
  for (size_t i=0 ; i < objectFileFilenames.size() ; i++)
    importObjectsFromFile(objectFileFilenames[i]);

  // Get the bounding box of all volumes of the first model.
  if(modelStates.size() > 0 && modelStates[0].volumes.size() > 0) {
    ospGetVec3f(modelStates[0].volumes[0], "boundingBoxMin", (osp::vec3f*)&boundingBox.lower);
    ospGetVec3f(modelStates[0].volumes[0], "boundingBoxMax", (osp::vec3f*)&boundingBox.upper);

    for (size_t i=1; i<modelStates[0].volumes.size(); i++) {
      ospcommon::box3f volumeBoundingBox;
      ospGetVec3f(modelStates[0].volumes[i], "boundingBoxMin", (osp::vec3f*)&volumeBoundingBox.lower);
      ospGetVec3f(modelStates[0].volumes[i], "boundingBoxMax", (osp::vec3f*)&volumeBoundingBox.upper);

      boundingBox.extend(volumeBoundingBox);
    }
  }
}
OSPLight OSPObjectFile::importLight(const tinyxml2::XMLNode *root)
{
  // Create the OSPRay object.
  OSPLight light = ospNewLight(NULL, root->ToElement()->Attribute("type"));

  // Iterate over object attributes.
  for (const tinyxml2::XMLNode *node = root->FirstChild() ; node ; node = node->NextSibling()) {

    // Light color.
    if (!strcmp(node->ToElement()->Name(), "color")) { importAttributeFloat3(node, light);  continue; }

    // Light direction.
    if (!strcmp(node->ToElement()->Name(), "direction")) { importAttributeFloat3(node, light);  continue; }

    // Light half angle for spot lights.
    if (!strcmp(node->ToElement()->Name(), "halfAngle")) { importAttributeFloat(node, light);  continue; }

    // Light position.
    if (!strcmp(node->ToElement()->Name(), "position")) { importAttributeFloat3(node, light);  continue; }

    // Light illumination distance cutoff.
    if (!strcmp(node->ToElement()->Name(), "range")) { importAttributeFloat(node, light);  continue; }

    // Error check.
    exitOnCondition(true, "unrecognized XML element type '" + std::string(node->ToElement()->Name()) + "'");
  }

  // The populated light object.
  return light;
}
void OSPObjectFile::importAttributeString(const tinyxml2::XMLNode *node, OSPObject parent)
{
  // Get the attribute value.
  const char *value = node->ToElement()->GetText();

  // Error check.
  exitOnCondition(strlen(value) == 0, "malformed XML element '" + std::string(node->ToElement()->Name()) + "'");

  // Set the attribute on the parent object.
  ospSetString(parent, node->ToElement()->Name(), value);
}
void OSPObjectFile::importAttributeInteger(const tinyxml2::XMLNode *node, OSPObject parent)
{
  // The attribute value is encoded in a string.
  const char *text = node->ToElement()->GetText();  int value = 0;  char guard[8];

  // Get the attribute value.
  exitOnCondition(sscanf(text, "%d %7s", &value, guard) != 1, "malformed XML element '" + std::string(node->ToElement()->Name()) + "'");

  // Set the attribute on the parent object.
  ospSet1i(parent, node->ToElement()->Name(), value);
}
  void GhostBlockBrickedVolume::createEquivalentISPC()
  {
    // Get the voxel type.
    voxelType = getParamString("voxelType", "unspecified");
    exitOnCondition(getVoxelType() == OSP_UNKNOWN,
                    "unrecognized voxel type (must be set before calling "
                    "ospSetRegion())");

    // Get the volume dimensions.
    this->dimensions = getParam3i("dimensions", vec3i(0));
    exitOnCondition(reduce_min(this->dimensions) <= 0,
                    "invalid volume dimensions (must be set before calling "
                    "ospSetRegion())");

    // Create an ISPC GhostBlockBrickedVolume object and assign type-specific
    // function pointers.
    ispcEquivalent = ispc::GBBV_createInstance(this,
                                         (int)getVoxelType(),
                                         (const ispc::vec3i &)this->dimensions);
  }
示例#8
0
  void OSPObjectFile::importAttributeFloat3(const tinyxml2::XMLNode *node, OSPObject parent) {

    //! The attribute value is encoded in a string.
    const char *text = node->ToElement()->GetText();  vec3f value = vec3f(0.0f);  char guard[8];

    //! Get the attribute value.
    exitOnCondition(sscanf(text, "%f %f %f %7s", &value.x, &value.y, &value.z, guard) != 3, "malformed XML element '" + std::string(node->ToElement()->Name()) + "'");

    //! Set the attribute on the parent object.
    ospSetVec3f(parent, node->ToElement()->Name(), value);

  }
示例#9
0
  void BlockBrickedVolume::createEquivalentISPC() 
  {
    //! Get the voxel type.
    voxelType = getParamString("voxelType", "unspecified");  exitOnCondition(getVoxelType() == OSP_UNKNOWN, "unrecognized voxel type");

    //! Create an ISPC BlockBrickedVolume object and assign type-specific function pointers.
    ispcEquivalent = ispc::BlockBrickedVolume_createInstance((int) getVoxelType());

    //! Get the volume dimensions.
    volumeDimensions = getParam3i("dimensions", vec3i(0));  exitOnCondition(reduce_min(volumeDimensions) <= 0, "invalid volume dimensions");

    //! Get the transfer function.
    transferFunction = (TransferFunction *) getParamObject("transferFunction", NULL);  exitOnCondition(transferFunction == NULL, "no transfer function specified");

    //! Get the value range.
    //! Voxel range not used for now.
    // vec2f voxelRange = getParam2f("voxelRange", vec2f(0.0f));  exitOnCondition(voxelRange == vec2f(0.0f), "no voxel range specified");

    //! Get the gamma correction coefficient and exponent.
    vec2f gammaCorrection = getParam2f("gammaCorrection", vec2f(1.0f));

    //! Set the volume dimensions.
    ispc::BlockBrickedVolume_setVolumeDimensions(ispcEquivalent, (const ispc::vec3i &) volumeDimensions);

    //! Set the value range (must occur before setting the transfer function).
    //ispc::BlockBrickedVolume_setValueRange(ispcEquivalent, (const ispc::vec2f &) voxelRange);

    //! Set the transfer function.
    ispc::BlockBrickedVolume_setTransferFunction(ispcEquivalent, transferFunction->getEquivalentISPC());

    //! Set the recommended sampling rate for ray casting based renderers.
    ispc::BlockBrickedVolume_setSamplingRate(ispcEquivalent, getParam1f("samplingRate", 1.0f));

    //! Set the gamma correction coefficient and exponent.
    ispc::BlockBrickedVolume_setGammaCorrection(ispcEquivalent, (const ispc::vec2f &) gammaCorrection);

    //! Allocate memory for the voxel data in the ISPC object.
    ispc::BlockBrickedVolume_allocateMemory(ispcEquivalent);

  }
  void GhostBlockBrickedVolume::commit()
  {
    // The ISPC volume container should already exist. We (currently)
    // require 'dimensions' etc to be set first, followed by call(s)
    // to 'setRegion', and only a final commit at the
    // end. 'dimensions' etc may/will _not_ be committed before
    // setregion.
    exitOnCondition(ispcEquivalent == nullptr,
                    "the volume data must be set via ospSetRegion() "
                    "prior to commit for this volume type");

    // StructuredVolume commit actions.
    StructuredVolume::commit();
  }
示例#11
0
  OSPObjectCatalog OSPObjectFile::importObject(const tinyxml2::XMLNode *node) {

    //! OSPRay light object.
    if (!strcmp(node->ToElement()->Name(), "light")) return(importLight(node));

    //! OSPRay triangle mesh object.
    if (!strcmp(node->ToElement()->Name(), "triangleMesh")) return(importTriangleMesh(node));

    //! OSPRay volume object.
    if (!strcmp(node->ToElement()->Name(), "volume")) return(importVolume(node));

    //! No other object types are currently supported.
    exitOnCondition(true, "unrecognized XML element type '" + std::string(node->ToElement()->Name()) + "'");  return(NULL);

  }
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;
}
示例#13
0
  OSPLoadDataMode OSPObjectFile::importLoadDataMode(const tinyxml2::XMLNode *node) {

    //! The flag is optionally encoded in a string.
    const char *text = node->ToElement()->Attribute("mode");

    //! Load volume data immediately, data will be copied from the host to the device.
    if (text && !strcmp(text, "loadDataImmediate")) return(OSP_LOAD_DATA_IMMEDIATE);

    //! Defer the load of volume data to the device, no data copy is necessary.
    if (text == NULL || !strcmp(text, "loadDataDeferred")) return(OSP_LOAD_DATA_DEFERRED);

    //! Error check.
    exitOnCondition(true, "malformed XML element '" + std::string(node->ToElement()->Name()) + "'");

    //! The program will never get here.
    return(OSP_LOAD_DATA_DEFERRED);

  }
OSPObject *OSPObjectFile::importObjects()
{
  // The XML document container.
  tinyxml2::XMLDocument xml(true, tinyxml2::COLLAPSE_WHITESPACE);

  // Read the XML object file.
  exitOnCondition(xml.LoadFile(filename.c_str()) != tinyxml2::XML_SUCCESS, "unable to read object file '" + filename + "'");

  // A list of OSPRay objects and their attributes contained in the file.
  std::vector<OSPObject> objects;

  // Iterate over the object entries, skip the XML declaration and comments.
  for (const tinyxml2::XMLNode *node = xml.FirstChild() ; node ; node = node->NextSibling()) if (node->ToElement()) objects.push_back(importObject(node));

  // Copy the objects into a list.
  OSPObject *pointer = new OSPObject[objects.size() + 1];  memcpy(pointer, &objects[0], objects.size() * sizeof(OSPObject));

  // Mark the end of the list.
  pointer[objects.size()] = NULL;  return(pointer);
}
示例#15
0
  OSPObjectCatalog OSPObjectFile::importObjects() {

    //! The XML document container.
    tinyxml2::XMLDocument xml(true, tinyxml2::COLLAPSE_WHITESPACE);

    //! Read the XML object file.
    exitOnCondition(xml.LoadFile(filename.c_str()) != tinyxml2::XML_SUCCESS, "unable to read object file '" + filename + "'");

    //! A catalog of the OSPRay objects and attributes contained in the file.
    ObjectCatalog *catalog = new ObjectCatalog();  std::vector<OSPObjectCatalog> entries;

    //! Iterate over the object entries, skip the XML declaration and comments.
    for (const tinyxml2::XMLNode *node = xml.FirstChild() ; node ; node = node->NextSibling()) if (node->ToElement()) entries.push_back(importObject(node));

    //! Copy the object entries into the catalog.
    catalog->entries = new OSPObjectCatalog[entries.size() + 1]();  memcpy(catalog->entries, &entries[0], entries.size() * sizeof(OSPObjectCatalog));

    //! The populated catalog.
    return(catalog);

  }
示例#16
0
  void OSPObjectFile::importLightAttribute(const tinyxml2::XMLNode *node, OSPLight light) {

    //! Light color.
    if (!strcmp(node->ToElement()->Name(), "color")) return(importAttributeFloat3(node, light));

    //! Light direction.
    if (!strcmp(node->ToElement()->Name(), "direction")) return(importAttributeFloat3(node, light));

    //! Light half angle for spot lights.
    if (!strcmp(node->ToElement()->Name(), "halfAngle")) return(importAttributeFloat(node, light));

    //! Light position.
    if (!strcmp(node->ToElement()->Name(), "position")) return(importAttributeFloat3(node, light));

    //! Light illumination distance cutoff.
    if (!strcmp(node->ToElement()->Name(), "range")) return(importAttributeFloat(node, light));

    //! Error check.
    exitOnCondition(true, "unrecognized XML element type '" + std::string(node->ToElement()->Name()) + "'");

  }
示例#17
0
  void OSPObjectFile::importVolumeAttribute(const tinyxml2::XMLNode *node, OSPVolume volume) {

    //! Volume size in voxels per dimension.
    if (!strcmp(node->ToElement()->Name(), "dimensions")) return(importAttributeInteger3(node, volume));

    //! File containing a volume specification and / or voxel data.
    if (!strcmp(node->ToElement()->Name(), "filename")) return(importVolumeFile(node, volume));

    //! Gamma correction coefficient and exponent.
    if (!strcmp(node->ToElement()->Name(), "gammaCorrection")) return(importAttributeFloat2(node, volume));

    //! Sampling rate for ray casting based renderers.
    if (!strcmp(node->ToElement()->Name(), "samplingRate")) return(importAttributeFloat(node, volume));

    //! Subvolume offset from origin within the full volume.
    if (!strcmp(node->ToElement()->Name(), "subvolumeOffsets")) return(importAttributeInteger3(node, volume));

    //! Subvolume dimensions within the full volume.
    if (!strcmp(node->ToElement()->Name(), "subvolumeDimensions")) return(importAttributeInteger3(node, volume));

    //! Subvolume steps in each dimension; can be used to subsample the volume.
    if (!strcmp(node->ToElement()->Name(), "subvolumeSteps")) return(importAttributeInteger3(node, volume));

    //! Voxel value range.
    if (!strcmp(node->ToElement()->Name(), "voxelRange")) return(importAttributeFloat2(node, volume));

    //! Voxel spacing in world coordinates (currently unused).
    if (!strcmp(node->ToElement()->Name(), "voxelSpacing")) return(importAttributeFloat3(node, volume));

    //! Voxel type string.
    if (!strcmp(node->ToElement()->Name(), "voxelType")) return(importAttributeString(node, volume));

    //! Error check.
    exitOnCondition(true, "unrecognized XML element type '" + std::string(node->ToElement()->Name()) + "'");

  }
示例#18
0
  void BlockBrickedVolume::updateEditableParameters() 
  {
    //! Get the transfer function.
    transferFunction = (TransferFunction *) getParamObject("transferFunction", NULL);  exitOnCondition(transferFunction == NULL, "no transfer function specified");

    //! Get the gamma correction coefficient and exponent.
    vec2f gammaCorrection = getParam2f("gammaCorrection", vec2f(1.0f));

    //! Set the gamma correction coefficient and exponent.
    ispc::BlockBrickedVolume_setGammaCorrection(ispcEquivalent, (const ispc::vec2f &) gammaCorrection);

    //! Set the recommended sampling rate for ray casting based renderers.
    ispc::BlockBrickedVolume_setSamplingRate(ispcEquivalent, getParam1f("samplingRate", 1.0f));

    //! Set the transfer function.
    ispc::BlockBrickedVolume_setTransferFunction(ispcEquivalent, transferFunction->getEquivalentISPC());

  }
OSPVolume OSPObjectFile::importVolume(const tinyxml2::XMLNode *root)
{
  const char *dpFromEnv = getenv("OSPRAY_DATA_PARALLEL");

  OSPVolume volume = NULL;
  if (dpFromEnv) {
    // Create the OSPRay object.
    osp::vec3i blockDims;
    int rc = sscanf(dpFromEnv,"%dx%dx%d",&blockDims.x,&blockDims.y,&blockDims.z);
    if (rc !=3)
      throw std::runtime_error("could not parse OSPRAY_DATA_PARALLEL env-var. Must be of format <X>x<Y>x<>Z (e.g., '4x4x4'");
    volume = ospNewVolume("data_distributed_volume");
    if (volume == NULL)
      throw std::runtime_error("#loaders.ospObjectFile: could not create volume ...");
   ospSetVec3i(volume,"num_dp_blocks",blockDims);
  } else {
    // Create the OSPRay object.
    volume = ospNewVolume("block_bricked_volume");
  }
  if (volume == NULL)
    throw std::runtime_error("#loaders.ospObjectFile: could not create volume ...");

  // Temporary storage for the file name attribute if specified.
  const char *volumeFilename = NULL;

  // Iterate over object attributes.
  for (const tinyxml2::XMLNode *node = root->FirstChild() ; node ; node = node->NextSibling()) {

    // Volume size in voxels per dimension.
    if (!strcmp(node->ToElement()->Name(), "dimensions")) { importAttributeInteger3(node, volume);  continue; }

    // File containing a volume specification and / or voxel data.
    if (!strcmp(node->ToElement()->Name(), "filename")) { volumeFilename = node->ToElement()->GetText();  continue; }

    // Grid origin in world coordinates.
    if (!strcmp(node->ToElement()->Name(), "gridOrigin")) { importAttributeFloat3(node, volume);  continue; }

    // Grid spacing in each dimension in world coordinates.
    if (!strcmp(node->ToElement()->Name(), "gridSpacing")) { importAttributeFloat3(node, volume);  continue; }

    // Sampling rate for ray casting based renderers.
    if (!strcmp(node->ToElement()->Name(), "samplingRate")) { importAttributeFloat(node, volume);  continue; }

    // Subvolume offset from origin within the full volume.
    if (!strcmp(node->ToElement()->Name(), "subvolumeOffsets")) { importAttributeInteger3(node, volume);  continue; }

    // Subvolume dimensions within the full volume.
    if (!strcmp(node->ToElement()->Name(), "subvolumeDimensions")) { importAttributeInteger3(node, volume);  continue; }

    // Subvolume steps in each dimension; can be used to subsample the volume.
    if (!strcmp(node->ToElement()->Name(), "subvolumeSteps")) { importAttributeInteger3(node, volume);  continue; }

    // Voxel value range.
    if (!strcmp(node->ToElement()->Name(), "voxelRange")) { importAttributeFloat2(node, volume);  continue; }

    // Voxel type string.
    if (!strcmp(node->ToElement()->Name(), "voxelType")) { importAttributeString(node, volume);  continue; }

    // Error check.
    exitOnCondition(true, "unrecognized XML element type '" + std::string(node->ToElement()->Name()) + "'");
  }

  // Load the contents of the volume file if specified.
  if (volumeFilename != NULL) {

    // Some implementations of 'dirname()' are destructive.
    char *duplicateFilename = strdup(filename.c_str());

    // The volume file path is absolute.
    if (volumeFilename[0] == '/') 
      return(VolumeFile::importVolume(volumeFilename, volume));

    // The volume file path is relative to the object file path.
    if (volumeFilename[0] != '/') 
      return(VolumeFile::importVolume((std::string(dirname(duplicateFilename)) + "/" + volumeFilename).c_str(), volume));

    // Free the temporary character array.
    if (duplicateFilename != NULL) free(duplicateFilename);
  }

  // The populated volume object.
  return volume;
}