Beispiel #1
0
 BBox3fa SceneTriangle1v::update(char* prim, size_t num, void* geom) const 
 {
   BBox3fa bounds = empty;
   Scene* scene = (Scene*) geom;
   
   for (size_t j=0; j<num; j++) 
   {
     Triangle1v& dst = ((Triangle1v*) prim)[j];
     const unsigned geomID = dst.geomID();
     const unsigned primID = dst.primID();
     const TriangleMesh* mesh = scene->getTriangleMesh(geomID);
     const TriangleMesh::Triangle& tri = mesh->triangle(primID);
     const Vec3fa v0 = mesh->vertex(tri.v[0]);
     const Vec3fa v1 = mesh->vertex(tri.v[1]);
     const Vec3fa v2 = mesh->vertex(tri.v[2]);
     new (&dst) Triangle1v(v0,v1,v2,geomID,primID,mesh->mask);
     bounds.extend(merge(BBox3fa(v0),BBox3fa(v1),BBox3fa(v2)));
   }
   return bounds; 
 }
Beispiel #2
0
 std::pair<BBox3fa,BBox3fa> Triangle1vMBType::update2(char* prim, size_t num, void* geom) const 
 {
   BBox3fa bounds0 = empty, bounds1 = empty;
   
   for (size_t j=0; j<num; j++) 
   {
     const Triangle1vMB& tri = ((Triangle1vMB*) prim)[j];
     bounds0.extend(merge(BBox3fa(tri.v0),BBox3fa(tri.v1),BBox3fa(tri.v2)));
     bounds1.extend(merge(BBox3fa(tri.v0+tri.d0),BBox3fa(tri.v1+tri.d1),BBox3fa(tri.v2+tri.d2)));
   }
   return std::pair<BBox3fa,BBox3fa>(bounds0,bounds1);
 }
    BBox3fa BVHNRefitter<N>::refit_toplevel(NodeRef& ref,
                                            size_t &subtrees,
											const BBox3fa *const subTreeBounds,
                                            const size_t depth)
    {
      if (depth >= MAX_SUB_TREE_EXTRACTION_DEPTH) 
      {
        assert(subtrees < MAX_NUM_SUB_TREES);
        assert(subTrees[subtrees] == ref);
        return subTreeBounds[subtrees++];
      }

      if (ref.isAlignedNode())
      {
        AlignedNode* node = ref.alignedNode();
        BBox3fa bounds[N];

        for (size_t i=0; i<N; i++)
        {
          NodeRef& child = node->child(i);

          if (unlikely(child == BVH::emptyNode)) 
            bounds[i] = BBox3fa(empty);
          else
            bounds[i] = refit_toplevel(child,subtrees,subTreeBounds,depth+1); 
        }
        
        BBox3vf<N> boundsT = transpose<N>(bounds);
      
        /* set new bounds */
        node->lower_x = boundsT.lower.x;
        node->lower_y = boundsT.lower.y;
        node->lower_z = boundsT.lower.z;
        node->upper_x = boundsT.upper.x;
        node->upper_y = boundsT.upper.y;
        node->upper_z = boundsT.upper.z;
        
        return merge<N>(bounds);
      }
      else
        return leafBounds.leafBounds(ref);
    }
    BBox3fa BVHNRefitter<N>::recurse_bottom(NodeRef& ref)
    {
      /* this is a leaf node */
      if (unlikely(ref.isLeaf()))
        return leafBounds.leafBounds(ref);
      
      /* recurse if this is an internal node */
      AlignedNode* node = ref.alignedNode();

      /* enable exclusive prefetch for >= AVX platforms */      
#if defined(__AVX__)      
      ref.prefetchW();
#endif      
      BBox3fa bounds[N];

      for (size_t i=0; i<N; i++)
        if (unlikely(node->child(i) == BVH::emptyNode))
        {
          bounds[i] = BBox3fa(empty);          
        }
      else
        bounds[i] = recurse_bottom(node->child(i));
      
      /* AOS to SOA transform */
      BBox3vf<N> boundsT = transpose<N>(bounds);
      
      /* set new bounds */
      node->lower_x = boundsT.lower.x;
      node->lower_y = boundsT.lower.y;
      node->lower_z = boundsT.lower.z;
      node->upper_x = boundsT.upper.x;
      node->upper_y = boundsT.upper.y;
      node->upper_z = boundsT.upper.z;

      return merge<N>(bounds);
    }
Beispiel #5
0
  BBox3fa TriangleMeshTriangle1v::update(char* prim_i, size_t num, void* geom) const 
  {
    BBox3fa bounds = empty;
    const TriangleMesh* mesh = (const TriangleMesh*) geom;
    Triangle1v* prim = (Triangle1v*) prim_i;

    if (num == -1)
    {
      while (true)
      {
	const unsigned geomID = prim->geomID<1>();
	const unsigned primID = prim->primID<1>();
	const TriangleMesh::Triangle& tri = mesh->triangle(primID);
	const Vec3fa v0 = mesh->vertex(tri.v[0]);
	const Vec3fa v1 = mesh->vertex(tri.v[1]);
	const Vec3fa v2 = mesh->vertex(tri.v[2]);
	const bool last = prim->last();
	new (prim) Triangle1v(v0,v1,v2,geomID,primID,mesh->mask,last);
	bounds.extend(merge(BBox3fa(v0),BBox3fa(v1),BBox3fa(v2)));
	if (last) break;
	prim++;
      }
    }
    else
    {
      for (size_t i=0; i<num; i++, prim++)
      {
	const unsigned geomID = prim->geomID<0>();
	const unsigned primID = prim->primID<0>();
	const TriangleMesh::Triangle& tri = mesh->triangle(primID);
	const Vec3fa v0 = mesh->vertex(tri.v[0]);
	const Vec3fa v1 = mesh->vertex(tri.v[1]);
	const Vec3fa v2 = mesh->vertex(tri.v[2]);
	new (prim) Triangle1v(v0,v1,v2,geomID,primID,mesh->mask,false);
	bounds.extend(merge(BBox3fa(v0),BBox3fa(v1),BBox3fa(v2)));
      }
    }
    return bounds; 
  }
Beispiel #6
0
  std::pair<BBox3fa,BBox3fa> TriangleMeshTriangle1vMB::update2(char* prim_i, size_t num, void* geom) const 
  {
    BBox3fa bounds0 = empty, bounds1 = empty;
    Triangle1vMB* prim = (Triangle1vMB*) prim_i;

    if (num == -1)
    {
      while (true)
      {
	bounds0.extend(merge(BBox3fa(prim->v0),BBox3fa(prim->v1),BBox3fa(prim->v2)));
	bounds1.extend(merge(BBox3fa(prim->v0+prim->d0),BBox3fa(prim->v1+prim->d1),BBox3fa(prim->v2+prim->d2)));
	const bool last = prim->last();
	if (last) break;
	prim++;
      }
    }
    else
    {
      for (size_t i=0; i<num; i++, prim++)
      {
	bounds0.extend(merge(BBox3fa(prim->v0),BBox3fa(prim->v1),BBox3fa(prim->v2)));
	bounds1.extend(merge(BBox3fa(prim->v0+prim->d0),BBox3fa(prim->v1+prim->d1),BBox3fa(prim->v2+prim->d2)));
      }
    }
    return std::pair<BBox3fa,BBox3fa>(bounds0,bounds1);
  }
Beispiel #7
0
void build_morton(vector_t<PrimRef>& prims, isa::PrimInfo& pinfo)
{
  size_t N = pinfo.size();
  /* array for morton builder */
  vector_t<isa::MortonID32Bit> morton_src(N);
  vector_t<isa::MortonID32Bit> morton_tmp(N);
  for (size_t i=0; i<N; i++) 
    morton_src[i].index = i;

  /* fast allocator that supports thread local operation */
  FastAllocator allocator;

  for (size_t i=0; i<2; i++)
  {
    std::cout << "iteration " << i << ": building BVH over " << N << " primitives, " << std::flush;
    double t0 = getSeconds();
    
    allocator.reset();

    std::pair<Node*,BBox3fa> node_bounds = isa::bvh_builder_morton<Node*>(

      /* thread local allocator for fast allocations */
      [&] () -> FastAllocator::ThreadLocal* { 
        return allocator.threadLocal(); 
      },

      BBox3fa(empty),

      /* lambda function that allocates BVH nodes */
      [&] ( isa::MortonBuildRecord<Node*>& current, isa::MortonBuildRecord<Node*>* children, size_t N, FastAllocator::ThreadLocal* alloc ) -> InnerNode*
      {
        assert(N <= 2);
        InnerNode* node = new (alloc->malloc(sizeof(InnerNode))) InnerNode;
        *current.parent = node;
        for (size_t i=0; i<N; i++) 
          children[i].parent = &node->children[i];
        return node;
      },

      /* lambda function that sets bounds */
      [&] (InnerNode* node, const BBox3fa* bounds, size_t N) -> BBox3fa
      {
        BBox3fa res = empty;
        for (size_t i=0; i<N; i++) {
          const BBox3fa b = bounds[i];
          res.extend(b);
          node->bounds[i] = b;
        }
        return res;
      },

      /* lambda function that creates BVH leaves */
      [&]( isa::MortonBuildRecord<Node*>& current, FastAllocator::ThreadLocal* alloc, BBox3fa& box_o) -> Node*
      {
        assert(current.size() == 1);
        const size_t id = morton_src[current.begin].index;
        const BBox3fa bounds = prims[id].bounds(); // FIXME: dont use morton_src, should be input
        Node* node = new (alloc->malloc(sizeof(LeafNode))) LeafNode(id,bounds);
        *current.parent = node;
        box_o = bounds;
        return node;
      },

      /* lambda that calculates the bounds for some primitive */
      [&] (const isa::MortonID32Bit& morton) -> BBox3fa {
        return prims[morton.index].bounds();
      },

      /* progress monitor function */
      [&] (size_t dn) { 
        // throw an exception here to cancel the build operation
      },

      morton_src.data(),morton_tmp.data(),prims.size(),2,1024,1,1);

    Node* root = node_bounds.first;
    
    double t1 = getSeconds();

    std::cout << 1000.0f*(t1-t0) << "ms, " << 1E-6*double(N)/(t1-t0) << " Mprims/s, sah = " << root->sah() << " [DONE]" << std::endl;
  }
}
Beispiel #8
0
  static void parseCommandLine(Ref<ParseStream> cin, const FileName& path)
  {
    while (true)
    {
      std::string tag = cin->getString();
      if (tag == "") return;

      /* parse command line parameters from a file */
      else if (tag == "-c") {
        FileName file = path + cin->getFileName();
        parseCommandLine(new ParseStream(new LineCommentFilter(file, "#")), file.path());
      }

      /* load model */
      else if (tag == "-i") {
        g_scene->add(SceneGraph::load(path + cin->getFileName()));
      }

      /* convert triangles to quads */
      else if (tag == "-convert-triangles-to-quads") {
        g_scene->triangles_to_quads();
      }

      /* convert to subdivs */
      else if (tag == "-convert-to-subdivs") {
        g_scene->triangles_to_quads();
        g_scene->quads_to_subdivs();
      }

      /* convert bezier to lines */
      else if (tag == "-convert-bezier-to-lines") {
        g_scene->bezier_to_lines();
      }

      /* load terrain */
      else if (tag == "-terrain") 
      {
        Ref<Image> tex = loadImage(path + cin->getFileName());
        const Vec3fa lower = cin->getVec3fa();
        const Vec3fa upper = cin->getVec3fa();
        g_height_field = new HeightField(tex,BBox3fa(lower,upper));
        g_scene->add(g_height_field->geometry());
      }

      /* distribute model */
      else if (tag == "-distribute") {
        Ref<SceneGraph::Node> object = SceneGraph::load(path + cin->getFileName());
        Ref<Image> distribution = loadImage(path + cin->getFileName());
        const float minDistance = cin->getFloat();
        const size_t N = cin->getInt();
        Ref<Instantiator> instantiator = new Instantiator(g_height_field,object,distribution,minDistance,N);
        instantiator->instantiate(g_scene);
      }

      /* instantiate model a single time */
      else if (tag == "-instantiate") {
        Ref<SceneGraph::Node> object = SceneGraph::load(path + cin->getFileName());
        const float px = cin->getFloat();
        const float py = cin->getFloat();
        const Vec2f p(px,py);
        const float angle = cin->getFloat()/180.0f*float(pi);
        const AffineSpace3fa space = g_height_field->get(p)*AffineSpace3fa::rotate(Vec3fa(0,1,0),angle);
        g_scene->add(new SceneGraph::TransformNode(space,object));
      }

      /* enable texture embedding */
      else if (tag == "-embed-textures") {
        embedTextures = true;
      }

      /* enable texture referencing */
      else if (tag == "-reference-textures") {
        embedTextures = false;
      }

      /* output filename */
      else if (tag == "-o") {
        SceneGraph::store(g_scene.dynamicCast<SceneGraph::Node>(),path + cin->getFileName(),embedTextures);
      }

      /* skip unknown command line parameter */
      else {
        std::cerr << "unknown command line parameter: " << tag << " ";
        while (cin->peek() != "" && cin->peek()[0] != '-') std::cerr << cin->getString() << " ";
        std::cerr << std::endl;
      }
    }
  }