Beispiel #1
0
Object::ptr CutGeometry::cutGeometry(Object::const_ptr object) const {

   auto coords = Coords::as(object);
   if (!coords)
       return Object::ptr();

   IsoDataFunctor decider = isocontrol.newFunc(object->getTransform(), &coords->x()[0], &coords->y()[0], &coords->z()[0]);

   switch (object->getType()) {
      case Object::TRIANGLES: {

         PlaneClip cutter(Triangles::as(object), decider);
         cutter.process();
         return cutter.result();
      }

      case Object::POLYGONS: {

         PlaneClip cutter(Polygons::as(object), decider);
         cutter.process();
         return cutter.result();
      }

      default:
         break;
   }
   return Object::ptr();
}
Beispiel #2
0
void PlaceHolder::setReal(Object::const_ptr r) {

   if (Object::const_ptr old = real())
      old->unref();
   d()->real = r->d();
   if (r)
      r->ref();
}
Beispiel #3
0
shm_handle_t Shm::getHandleFromObject(Object::const_ptr object) const {

#ifdef NO_SHMEM
   return object->d();
#else
   try {
      return m_shm->get_handle_from_address(object->d());

   } catch (interprocess_exception &) { }

   return 0;
#endif
}
Beispiel #4
0
bool Object::Data::addAttachment(const std::string &key, Object::const_ptr obj) {

   boost::interprocess::scoped_lock<boost::interprocess::interprocess_recursive_mutex> lock(attachment_mutex);
   const Key skey(key.c_str(), Shm::the().allocator());
   AttachmentMap::iterator it = attachments->find(skey);
   if (it != attachments->end()) {
      return false;
   }

   obj->ref();
   attachments->insert(AttachmentMapValueType(skey, obj->d()));

   return true;
}
Beispiel #5
0
bool Object::Data::addAttachment(const std::string &key, Object::const_ptr obj) {

   attachment_mutex_lock_type lock(attachment_mutex);
   const Key skey(key.c_str(), Shm::the().allocator());
   AttachmentMap::const_iterator it = attachments.find(skey);
   if (it != attachments.end()) {
      return false;
   }

   obj->ref();
   attachments.insert(AttachmentMapValueType(skey, obj->d()));

   return true;
}
Beispiel #6
0
bool ColorAttribute::compute() {

   //std::cerr << "ColorAttribute: compute: execcount=" << m_executionCount << std::endl;

   auto color = p_color->getValue();
   Object::const_ptr obj = expect<Object>("data_in");
   if (!obj)
      return false;

   Object::ptr out = obj->clone();
   out->addAttribute("_color", color);
   addObject("data_out", out);

   return true;
}
Beispiel #7
0
Object::const_ptr Shm::getObjectFromHandle(const shm_handle_t & handle) const {
    
    Object::const_ptr ret;
    lockObjects();
    Object::Data *od = getObjectDataFromHandle(handle);
    if (od) {
        od->ref();
        unlockObjects();
        ret.reset(Object::create(od));
        od->unref();
    } else {
        unlockObjects();
    }
    return ret;
}
Beispiel #8
0
bool AttachObject::compute() {

   //std::cerr << "AttachObject: compute: execcount=" << m_executionCount << std::endl;

   Object::const_ptr obj = expect<Object>("data_in");
   if (!obj)
      return false;

   Object::ptr out = std::const_pointer_cast<Object>(obj);
   Object::ptr att(new Points(4));
   obj->addAttachment("test", att);

   addObject("data_out", out);

   return true;
}
Beispiel #9
0
void Object::copyAttributes(Object::const_ptr src, bool replace) {

   if (replace) {
      auto &m = d()->meta;
      auto &sm = src->meta();
      m.setBlock(sm.block());
      m.setNumBlocks(sm.numBlocks());
      m.setTimeStep(sm.timeStep());
      m.setNumTimesteps(sm.numTimesteps());
      m.setRealTime(sm.realTime());
      m.setAnimationStep(sm.animationStep());
      m.setNumAnimationSteps(sm.numAnimationSteps());
      m.setIteration(sm.iteration());
   }

   d()->copyAttributes(src->d(), replace);
}
Beispiel #10
0
bool AddAttribute::compute() {

   Object::const_ptr obj = expect<Object>("data_in");
   if (!obj)
      return true;

   Object::ptr out = obj->clone();

   for (int i=0; i<NumAttributes; ++i) {
      if (!p_name[i]->getValue().empty()) {
         out->addAttribute(p_name[i]->getValue(), p_value[i]->getValue());
      }
   }

   addObject("data_out", out);

   return true;
}
Beispiel #11
0
bool ObjectStatistics::compute() {

   //std::cerr << "ObjectStatistics: compute: execcount=" << m_executionCount << std::endl;

   Object::const_ptr obj = expect<Object>("data_in");
   if (!obj)
      return true;

   if (obj->getTimestep()+1 > m_timesteps)
      m_timesteps = obj->getTimestep()+1;

   stats s;
   if (auto i = Indexed::as(obj)) {
      s.elements = i->getNumElements();
      s.vertices = i->getNumCorners();
   } else if (auto t = Triangles::as(obj)) {
      s.elements = t->getNumElements();
      s.vertices = t->getNumCorners();
   }
   if (auto c = Coords::as(obj)) {
      s.coords = c->getNumCoords();
      if (c->normals())
         ++s.normals;
   } else if (auto d = DataBase::as(obj)) {
      if (d->grid())
         ++s.grids;
      if(auto v = Vec<Scalar, 3>::as(obj)) {
         s.data[3] = v->getSize();
      } else if(auto v = Vec<Scalar, 1>::as(obj)) {
         s.data[1] = v->getSize();
      }
   }
   s.blocks = 1;
   m_cur += s;

   return true;
}
Beispiel #12
0
bool FilterNode::compute() {

   Object::const_ptr data = expect<Object>("data_in");
   if (!data)
      return true;

   const bool invert = m_invertParam->getValue();
   const Integer select = m_nodeParam->getValue();

   bool pass = true;
   switch (m_criterionParam->getValue()) {
   case Rank:
       pass = select == rank();
       break;
   case BlockNumber:
       pass = select == data->getBlock();
       break;
   case Timestep:
       pass = select == data->getTimestep();
       break;
   }

   if (invert)
      pass = !pass;

   if (pass) {
      passThroughObject("data_out", data);
   } else {
      Object::ptr obj = data->cloneType();
      obj->setMeta(data->meta());
      obj->copyAttributes(data);
      addObject("data_out", obj);
   }

   return true;
}
Beispiel #13
0
bool WriteVistle::compute() {

   int count = 0;
   bool trunc = false;
   bool end = false;
   std::string format;
   Object::const_ptr obj = expect<Object>("grid_in");
   if (!obj)
      return false;

   std::ios_base::openmode flags = std::ios::out;
   if (obj->hasAttribute("_mark_begin")) {
      close();
      trunc = true;
      flags |= std::ios::trunc;
   } else {
      flags |= std::ios::app;
   }
   if (obj->hasAttribute("_mark_end")) {
      end = true;
   }
   switch(getIntParameter("format")) {
      default:
      case 0:
         flags |= std::ios::binary;
         format = "binary";
         break;
      case 1:
         format = "text";
         break;
      case 2:
         format = "xml";
         break;
   }
   if (!m_ofs) {
      m_ofs = new std::ofstream(getStringParameter("filename").c_str(), flags);
   }
   if (trunc)
      *m_ofs << "vistle " << format << " 1 start" << std::endl;

   switch(getIntParameter("format")) {
      default:
      case 0:
      {
         if (!m_binAr)
            m_binAr = new ba::binary_oarchive(*m_ofs);
         obj->save(*m_binAr);
         break;
      }
      case 1:
      {
         if (!m_textAr)
            m_textAr = new ba::text_oarchive(*m_ofs);
         obj->save(*m_textAr);
         break;
      }
      case 2:
      {
         if (!m_xmlAr)
            m_xmlAr = new ba::xml_oarchive(*m_ofs);
         obj->save(*m_xmlAr);
         break;
      }
   }
   ++count;

   close();

   //*m_ofs << std::endl << "vistle separator" << std::endl;

   if (trunc) {
      std::cerr << "saved";
   } else {
      std::cerr << "appended";
   }
   if (end) {
      std::cerr << " final";
      close();
   }
   std::cerr << " [" << count << "] to " << getStringParameter("filename") << " (" << format << ")" << std::endl;

   return true;
}
Beispiel #14
0
void Object::copyAttachments(Object::const_ptr src, bool replace) {

   d()->copyAttachments(src->d(), replace);
}
Beispiel #15
0
RayRenderObject::RayRenderObject(RTCDevice device, int senderId, const std::string &senderPort,
      Object::const_ptr container,
      Object::const_ptr geometry,
      Object::const_ptr normals,
      Object::const_ptr texture)
: vistle::RenderObject(senderId, senderPort, container, geometry, normals, texture)
, data(new ispc::RenderObjectData)
{
   data->device = device;
   data->scene = nullptr;
   data->geomID = RTC_INVALID_GEOMETRY_ID;
   data->instID = RTC_INVALID_GEOMETRY_ID;
   data->spheres = nullptr;
   data->primitiveFlags = nullptr;
   data->indexBuffer = nullptr;
   data->texWidth = 0;
   data->texData = nullptr;
   data->texCoords = nullptr;
   data->lighted = 1;
   data->hasSolidColor = hasSolidColor;
   data->perPrimitiveMapping = 0;
   data->normalsPerPrimitiveMapping = 0;
   for (int c=0; c<3; ++c) {
       data->normalTransform[c].x = c==0 ? 1 : 0;
       data->normalTransform[c].y = c==1 ? 1 : 0;
       data->normalTransform[c].z = c==2 ? 1 : 0;
   }
   for (int c=0; c<3; ++c) {
       data->normals[c] = nullptr;
   }
   for (int c=0; c<4; ++c) {
      data->solidColor[c] = solidColor[c];
   }
   if (this->texture) {
      if (this->texture->guessMapping(geometry) == DataBase::Element)
         data->perPrimitiveMapping = 1;

      data->texWidth = this->texture->getWidth();
      data->texData = this->texture->pixels().data();
      data->texCoords = &this->texture->coords()[0];
   }
   if (geometry->isEmpty()) {
      return;
   }

   data->scene = rtcNewScene(data->device);
   rtcSetSceneFlags(data->scene, RTC_SCENE_FLAG_NONE);
   rtcSetSceneBuildQuality(data->scene, RTC_BUILD_QUALITY_MEDIUM);

   RTCGeometry geom = 0;
   bool useNormals = true;
   if (auto tri = Triangles::as(geometry)) {

      Index numElem = tri->getNumElements();
      geom = rtcNewGeometry (data->device, RTC_GEOMETRY_TYPE_TRIANGLE);
      rtcSetGeometryBuildQuality(geom,RTC_BUILD_QUALITY_MEDIUM);
      rtcSetGeometryTimeStepCount(geom,1);
      std::cerr << "Tri: #: " << tri->getNumElements() << ", #corners: " << tri->getNumCorners() << ", #coord: " << tri->getNumCoords() << std::endl;

      Vertex* vertices = (Vertex*) rtcSetNewGeometryBuffer(geom,RTC_BUFFER_TYPE_VERTEX,0,RTC_FORMAT_FLOAT3,4*sizeof(float),tri->getNumCoords());
      for (Index i=0; i<tri->getNumCoords(); ++i) {
         vertices[i].x = tri->x()[i];
         vertices[i].y = tri->y()[i];
         vertices[i].z = tri->z()[i];
      }
      

      //data->indexBuffer = new Triangle[numElem];
      //rtcSetSharedGeometryBuffer(geom_0,RTC_BUFFER_TYPE_INDEX,0,RTC_FORMAT_UINT3,data->indexBuffer,0,sizeof(Triangle),numElem);
      Triangle* triangles = (Triangle*) rtcSetNewGeometryBuffer(geom,RTC_BUFFER_TYPE_INDEX,0,RTC_FORMAT_UINT3,sizeof(Triangle),numElem);
      data->indexBuffer = triangles;
      if (tri->getNumCorners() == 0) {
         for (Index i=0; i<numElem; ++i) {
            triangles[i].v0 = i*3;
            triangles[i].v1 = i*3+1;
            triangles[i].v2 = i*3+2;
            triangles[i].elem = i;
         }
      } else {
         for (Index i=0; i<numElem; ++i) {
            triangles[i].v0 = tri->cl()[i*3];
            triangles[i].v1 = tri->cl()[i*3+1];
            triangles[i].v2 = tri->cl()[i*3+2];
            triangles[i].elem = i;
         }
      }
      
   } else if (auto poly = Polygons::as(geometry)) {

      Index ntri = poly->getNumCorners()-2*poly->getNumElements();
      vassert(ntri >= 0);

      geom = rtcNewGeometry (data->device, RTC_GEOMETRY_TYPE_TRIANGLE);
      rtcSetGeometryBuildQuality(geom,RTC_BUILD_QUALITY_MEDIUM);
      rtcSetGeometryTimeStepCount(geom,1);
      //std::cerr << "Poly: #tri: " << poly->getNumCorners()-2*poly->getNumElements() << ", #coord: " << poly->getNumCoords() << std::endl;

      Vertex* vertices = (Vertex*) rtcSetNewGeometryBuffer(geom,RTC_BUFFER_TYPE_VERTEX,0,RTC_FORMAT_FLOAT3,4*sizeof(float),poly->getNumCoords());
      for (Index i=0; i<poly->getNumCoords(); ++i) {
         vertices[i].x = poly->x()[i];
         vertices[i].y = poly->y()[i];
         vertices[i].z = poly->z()[i];
      }
      

      //data->indexBuffer = new Triangle[ntri];
      //rtcSetSharedGeometryBuffer(geom,RTC_BUFFER_TYPE_INDEX,0,RTC_FORMAT_UINT3,data->indexBuffer,0,sizeof(Triangle),ntri);
      Triangle* triangles = (Triangle*) rtcSetNewGeometryBuffer(geom,RTC_BUFFER_TYPE_INDEX,0,RTC_FORMAT_UINT3,sizeof(Triangle),ntri);
      data->indexBuffer = triangles;
      Index t = 0;
      for (Index i=0; i<poly->getNumElements(); ++i) {
         const Index start = poly->el()[i];
         const Index end = poly->el()[i+1];
         const Index nvert = end-start;
         const Index last = end-1;
         for (Index v=0; v<nvert-2; ++v) {
            triangles[t].elem = i;
            const Index v2 = v/2;
            if (v%2) {
               triangles[t].v0 = poly->cl()[last-v2];
               triangles[t].v1 = poly->cl()[start+v2+1];
               triangles[t].v2 = poly->cl()[last-v2-1];
            } else {
               triangles[t].v0 = poly->cl()[start+v2];
               triangles[t].v1 = poly->cl()[start+v2+1];
               triangles[t].v2 = poly->cl()[last-v2];
            }
            ++t;
         }
      }
      vassert(t == ntri);
      
   } else if (auto sph = Spheres::as(geometry)) {
      useNormals = false;

      Index nsph = sph->getNumSpheres();
      //std::cerr << "Spheres: #sph: " << nsph << std::endl;
      data->spheres = new ispc::Sphere[nsph];
      auto x = &sph->x()[0];
      auto y = &sph->y()[0];
      auto z = &sph->z()[0];
      auto r = &sph->r()[0];
      auto s = data->spheres;
      for (Index i=0; i<nsph; ++i) {
         s[i].p.x = x[i];
         s[i].p.y = y[i];
         s[i].p.z = z[i];
         s[i].r = r[i];
      }
      geom = newSpheres(data.get(), nsph);
   } else if (auto point = Points::as(geometry)) {

      Index np = point->getNumPoints();
      //std::cerr << "Points: #sph: " << np << std::endl;
      data->spheres = new ispc::Sphere[np];
      auto x = &point->x()[0];
      auto y = &point->y()[0];
      auto z = &point->z()[0];
      auto s = data->spheres;
      for (Index i=0; i<np; ++i) {
         s[i].p.x = x[i];
         s[i].p.y = y[i];
         s[i].p.z = z[i];
         s[i].r = pointSize;
      }
      data->lighted = 0;
      geom = newSpheres(data.get(), np);
   } else if (auto line = Lines::as(geometry)) {

      Index nStrips = line->getNumElements();
      Index nPoints = line->getNumCorners();
      std::cerr << "Lines: #strips: " << nStrips << ", #corners: " << nPoints << std::endl;
      data->primitiveFlags = new unsigned int[nPoints];
      data->spheres = new ispc::Sphere[nPoints];

      auto el = &line->el()[0];
      auto cl = &line->cl()[0];
      auto x = &line->x()[0];
      auto y = &line->y()[0];
      auto z = &line->z()[0];
      auto s = data->spheres;
      auto p = data->primitiveFlags;
      Index idx=0;
      for (Index strip=0; strip<nStrips; ++strip) {
         const Index begin = el[strip], end = el[strip+1];
         for (Index c=begin; c<end; ++c) {
            
            Index i = cl[c];
            s[idx].p.x = x[i];
            s[idx].p.y = y[i];
            s[idx].p.z = z[i];
            s[idx].r = pointSize;
            p[idx] = ispc::PFNone;
            if (c+1 != end)
               p[idx] |= ispc::PFCone;
            p[idx] |= ispc::PFStartSphere;
            ++idx;
         }
      }
      vassert(idx == nPoints);
      data->lighted = 0;
      geom = newTubes(data.get(), nPoints-1);
   } else if (auto tube = Tubes::as(geometry)) {
      useNormals= false;

      Index nStrips = tube->getNumTubes();
      Index nPoints = tube->getNumCoords();
      std::cerr << "Tubes: #strips: " << nStrips << ", #corners: " << nPoints << std::endl;
      data->primitiveFlags = new unsigned int[nPoints];
      data->spheres = new ispc::Sphere[nPoints];
      const Tubes::CapStyle startStyle = tube->startStyle(), jointStyle = tube->jointStyle(), endStyle = tube->endStyle();

      auto el = tube->components().data();
      auto x = &tube->x()[0];
      auto y = &tube->y()[0];
      auto z = &tube->z()[0];
      auto r = &tube->r()[0];
      auto s = data->spheres;
      auto p = data->primitiveFlags;
      Index idx=0;
      for (Index strip=0; strip<nStrips; ++strip) {
         const Index begin = el[strip], end = el[strip+1];
         vassert(idx == begin);
         for (Index i=begin; i<end; ++i) {
            
            s[idx].p.x = x[i];
            s[idx].p.y = y[i];
            s[idx].p.z = z[i];
            s[idx].r = r[i];

            p[idx] = ispc::PFNone;
            if (i == begin) {
               switch(startStyle) {
                  case Tubes::Flat:
                     p[idx] |= ispc::PFStartDisc;
                     break;
                  case Tubes::Round:
                     p[idx] |= ispc::PFStartSphere;
                     break;
                  default:
                     break;
               }
            } else if (i+1 != end) {
               if (jointStyle == Tubes::Flat) {
                  p[idx] |= ispc::PFStartDisc;
               }
            }

            if (i+1 != end) {
               p[idx] |= ispc::PFCone;

               switch((i+2==end) ? endStyle : jointStyle) {
                  case Tubes::Open:
                     break;
                  case Tubes::Flat:
                     p[idx] |= ispc::PFEndDisc;
                     break;
                  case Tubes::Round:
                     p[idx] |= i+2==end ? ispc::PFEndSphere : ispc::PFEndSphereSect;
                     break;
                  case Tubes::Arrow:
                     p[idx] |= ispc::PFArrow;
                     break;
               }
            }

            ++idx;
         }
         vassert(idx == end);
      }
      vassert(idx == nPoints);
      geom = newTubes(data.get(), nPoints > 0 ? nPoints-1 : 0);
   }

   if (geom) {
       if (this->normals && useNormals) {

           if (this->normals->guessMapping(geometry) == DataBase::Element)
               data->normalsPerPrimitiveMapping = 1;

           for (int c=0; c<3; ++c) {
               data->normals[c] = &this->normals->x(c)[0];
           }
       }

       data->geomID = rtcAttachGeometry(data->scene, geom);
       rtcReleaseGeometry(geom);
       rtcCommitGeometry(geom);
   }

   rtcCommitScene(data->scene);
}
Beispiel #16
0
RayRenderObject::RayRenderObject(RTCDevice device, int senderId, const std::string &senderPort,
      Object::const_ptr container,
      Object::const_ptr geometry,
      Object::const_ptr normals,
      Object::const_ptr colors,
      Object::const_ptr texture)
: vistle::RenderObject(senderId, senderPort, container, geometry, normals, colors, texture)
, data(new ispc::RenderObjectData)
{
   data->device = device;
   data->scene = nullptr;
   data->geomId = RTC_INVALID_GEOMETRY_ID;
   data->instId = RTC_INVALID_GEOMETRY_ID;
   data->spheres = nullptr;
   data->primitiveFlags = nullptr;
   data->indexBuffer = nullptr;
   data->texWidth = 0;
   data->texData = nullptr;
   data->texCoords = nullptr;
   data->lighted = 1;
   data->hasSolidColor = hasSolidColor;
   data->perPrimitiveMapping = 0;
   for (int c=0; c<4; ++c) {
      data->solidColor[c] = solidColor[c];
   }
   if (this->texture) {
      if (this->texture->guessMapping(geometry) == DataBase::Element)
         data->perPrimitiveMapping = 1;

      data->texWidth = this->texture->getWidth();
      data->texData = this->texture->pixels().data();
      data->texCoords = &this->texture->coords()[0];
   }

   if (geometry->isEmpty()) {
      return;
   }

   data->scene = rtcDeviceNewScene(data->device, RTC_SCENE_STATIC|sceneFlags, intersections);

   if (auto tri = Triangles::as(geometry)) {

      Index numElem = tri->getNumElements();
      if (numElem == 0) {
         numElem = tri->getNumCoords() / 3;
      }
      data->geomId = rtcNewTriangleMesh(data->scene, RTC_GEOMETRY_STATIC, numElem, tri->getNumCoords());
      std::cerr << "Tri: #tri: " << tri->getNumElements() << ", #coord: " << tri->getNumCoords() << std::endl;

      Vertex* vertices = (Vertex*) rtcMapBuffer(data->scene, data->geomId, RTC_VERTEX_BUFFER);
      for (Index i=0; i<tri->getNumCoords(); ++i) {
         vertices[i].x = tri->x()[i];
         vertices[i].y = tri->y()[i];
         vertices[i].z = tri->z()[i];
      }
      rtcUnmapBuffer(data->scene, data->geomId, RTC_VERTEX_BUFFER);

      data->indexBuffer = new Triangle[numElem];
      rtcSetBuffer(data->scene, data->geomId, RTC_INDEX_BUFFER, data->indexBuffer, 0, sizeof(Triangle));
      Triangle* triangles = (Triangle*) rtcMapBuffer(data->scene, data->geomId, RTC_INDEX_BUFFER);
      if (tri->getNumElements() == 0) {
         for (Index i=0; i<numElem; ++i) {
            triangles[i].v0 = i*3;
            triangles[i].v1 = i*3+1;
            triangles[i].v2 = i*3+2;
            triangles[i].elem = i;
         }
      } else {
         for (Index i=0; i<numElem; ++i) {
            triangles[i].v0 = tri->cl()[i*3];
            triangles[i].v1 = tri->cl()[i*3+1];
            triangles[i].v2 = tri->cl()[i*3+2];
            triangles[i].elem = i;
         }
      }
      rtcUnmapBuffer(data->scene, data->geomId, RTC_INDEX_BUFFER);
   } else if (auto poly = Polygons::as(geometry)) {

      Index ntri = poly->getNumCorners()-2*poly->getNumElements();
      vassert(ntri >= 0);

      data->geomId = rtcNewTriangleMesh(data->scene, RTC_GEOMETRY_STATIC, ntri, poly->getNumCoords());
      //std::cerr << "Poly: #tri: " << poly->getNumCorners()-2*poly->getNumElements() << ", #coord: " << poly->getNumCoords() << std::endl;

      Vertex* vertices = (Vertex*) rtcMapBuffer(data->scene, data->geomId, RTC_VERTEX_BUFFER);
      for (Index i=0; i<poly->getNumCoords(); ++i) {
         vertices[i].x = poly->x()[i];
         vertices[i].y = poly->y()[i];
         vertices[i].z = poly->z()[i];
      }
      rtcUnmapBuffer(data->scene, data->geomId, RTC_VERTEX_BUFFER);

      data->indexBuffer = new Triangle[ntri];
      rtcSetBuffer(data->scene, data->geomId, RTC_INDEX_BUFFER, data->indexBuffer, 0, sizeof(Triangle));
      Triangle* triangles = (Triangle*) rtcMapBuffer(data->scene, data->geomId, RTC_INDEX_BUFFER);
      Index t = 0;
      for (Index i=0; i<poly->getNumElements(); ++i) {
         const Index start = poly->el()[i];
         const Index end = poly->el()[i+1];
         const Index nvert = end-start;
         const Index last = end-1;
         for (Index v=0; v<nvert-2; ++v) {
            triangles[t].elem = i;
            const Index v2 = v/2;
            if (v%2) {
               triangles[t].v0 = poly->cl()[last-v2];
               triangles[t].v1 = poly->cl()[start+v2+1];
               triangles[t].v2 = poly->cl()[last-v2-1];
            } else {
               triangles[t].v0 = poly->cl()[start+v2];
               triangles[t].v1 = poly->cl()[start+v2+1];
               triangles[t].v2 = poly->cl()[last-v2];
            }
            ++t;
         }
      }
      vassert(t == ntri);
      rtcUnmapBuffer(data->scene, data->geomId, RTC_INDEX_BUFFER);
   } else if (auto sph = Spheres::as(geometry)) {

      Index nsph = sph->getNumSpheres();
      //std::cerr << "Spheres: #sph: " << nsph << std::endl;
      data->spheres = new ispc::Sphere[nsph];
      auto x = &sph->x()[0];
      auto y = &sph->y()[0];
      auto z = &sph->z()[0];
      auto r = &sph->r()[0];
      auto s = data->spheres;
      for (Index i=0; i<nsph; ++i) {
         s[i].p.x = x[i];
         s[i].p.y = y[i];
         s[i].p.z = z[i];
         s[i].r = r[i];
      }
      data->geomId = registerSpheres((ispc::__RTCScene *)data->scene, data.get(), nsph);
   } else if (auto point = Points::as(geometry)) {

      Index np = point->getNumPoints();
      //std::cerr << "Points: #sph: " << np << std::endl;
      data->spheres = new ispc::Sphere[np];
      auto x = &point->x()[0];
      auto y = &point->y()[0];
      auto z = &point->z()[0];
      auto s = data->spheres;
      for (Index i=0; i<np; ++i) {
         s[i].p.x = x[i];
         s[i].p.y = y[i];
         s[i].p.z = z[i];
         s[i].r = pointSize;
      }
      data->lighted = 0;
      data->geomId = registerSpheres((ispc::__RTCScene *)data->scene, data.get(), np);
   } else if (auto line = Lines::as(geometry)) {

      Index nStrips = line->getNumElements();
      Index nPoints = line->getNumCorners();
      std::cerr << "Lines: #strips: " << nStrips << ", #corners: " << nPoints << std::endl;
      data->primitiveFlags = new unsigned int[nPoints];
      data->spheres = new ispc::Sphere[nPoints];

      auto el = &line->el()[0];
      auto cl = &line->cl()[0];
      auto x = &line->x()[0];
      auto y = &line->y()[0];
      auto z = &line->z()[0];
      auto s = data->spheres;
      auto p = data->primitiveFlags;
      Index idx=0;
      for (Index strip=0; strip<nStrips; ++strip) {
         const Index begin = el[strip], end = el[strip+1];
         for (Index c=begin; c<end; ++c) {
            
            Index i = cl[c];
            s[idx].p.x = x[i];
            s[idx].p.y = y[i];
            s[idx].p.z = z[i];
            s[idx].r = pointSize;
            p[idx] = ispc::PFNone;
            if (c+1 != end)
               p[idx] |= ispc::PFCone;
            p[idx] |= ispc::PFStartSphere;
            ++idx;
         }
      }
      vassert(idx == nPoints);
      data->lighted = 0;
      data->geomId = registerTubes((ispc::__RTCScene *)data->scene, data.get(), nPoints-1);
   } else if (auto tube = Tubes::as(geometry)) {

      Index nStrips = tube->getNumTubes();
      Index nPoints = tube->getNumCoords();
      std::cerr << "Tubes: #strips: " << nStrips << ", #corners: " << nPoints << std::endl;
      data->primitiveFlags = new unsigned int[nPoints];
      data->spheres = new ispc::Sphere[nPoints];
      const Tubes::CapStyle startStyle = tube->startStyle(), jointStyle = tube->jointStyle(), endStyle = tube->endStyle();

      auto el = tube->components().data();
      auto x = &tube->x()[0];
      auto y = &tube->y()[0];
      auto z = &tube->z()[0];
      auto r = &tube->r()[0];
      auto s = data->spheres;
      auto p = data->primitiveFlags;
      Index idx=0;
      for (Index strip=0; strip<nStrips; ++strip) {
         const Index begin = el[strip], end = el[strip+1];
         vassert(idx == begin);
         for (Index i=begin; i<end; ++i) {
            
            s[idx].p.x = x[i];
            s[idx].p.y = y[i];
            s[idx].p.z = z[i];
            s[idx].r = r[i];

            p[idx] = ispc::PFNone;
            if (i == begin) {
               switch(startStyle) {
                  case Tubes::Flat:
                     p[idx] |= ispc::PFStartDisc;
                     break;
                  case Tubes::Round:
                     p[idx] |= ispc::PFStartSphere;
                     break;
                  default:
                     break;
               }
            } else if (i+1 != end) {
               if (jointStyle == Tubes::Flat) {
                  p[idx] |= ispc::PFStartDisc;
               }
            }

            if (i+1 != end) {
               p[idx] |= ispc::PFCone;

               switch((i+2==end) ? endStyle : jointStyle) {
                  case Tubes::Open:
                     break;
                  case Tubes::Flat:
                     p[idx] |= ispc::PFEndDisc;
                     break;
                  case Tubes::Round:
                     p[idx] |= i+2==end ? ispc::PFEndSphere : ispc::PFEndSphereSect;
                     break;
                  case Tubes::Arrow:
                     p[idx] |= ispc::PFArrow;
                     break;
               }
            }

            ++idx;
         }
         vassert(idx == end);
      }
      vassert(idx == nPoints);
      data->geomId = registerTubes((ispc::__RTCScene *)data->scene, data.get(), nPoints > 0 ? nPoints-1 : 0);
   }

   rtcCommit(data->scene);
}