Example #1
0
/**
 * Recursively intersects Ray Charles with his node and returns the distance to
 * the closest intersection and a stores the id of the sphere in sphereId.
 */
inline float Intersect(const Ray charles, float t, 
                       const BVHNode& node, const vector<BVHNode>& nodes, 
                       const vector<Sphere> spheres, unsigned int &sphereId) {

    if (node.GetType() == BVHNode::LEAF) {
        // Intersect leaf
        return Exhaustive(charles, t, node, spheres, sphereId);
    } else {
        // Traverse further
        const BVHNode left = nodes[node.GetLeftChild()];
        float tLeft;
        if (!left.aabb.ClosestIntersection(charles, tLeft)) tLeft = 1e32f;
        
        const BVHNode right = nodes[node.GetRightChild()];
        float tRight;
        if (!right.aabb.ClosestIntersection(charles, tRight)) tRight = 1e32f;
    
        if (tLeft < tRight) { // Intersect left first
            if (tLeft < t) t = Intersect(charles, t, left, nodes, spheres, sphereId);
            if (tRight < t) t = Intersect(charles, t, right, nodes, spheres, sphereId);
        } else { // Intersect right first
            if (tRight < t) t = Intersect(charles, t, right, nodes, spheres, sphereId);
            if (tLeft < t) t = Intersect(charles, t, left, nodes, spheres, sphereId);
        }

        return t;
    }
}
Example #2
0
void BVH::build(Progress& progress)
{
	progress.set_substatus("Building BVH");

	/* build nodes */
	BVHBuild bvh_build(objects,
	                   pack.prim_type,
	                   pack.prim_index,
	                   pack.prim_object,
	                   params,
	                   progress);
	BVHNode *root = bvh_build.run();

	if(progress.get_cancel()) {
		if(root) root->deleteSubtree();
		return;
	}

	/* pack triangles */
	progress.set_substatus("Packing BVH triangles and strands");
	pack_primitives();

	if(progress.get_cancel()) {
		root->deleteSubtree();
		return;
	}

	/* pack nodes */
	progress.set_substatus("Packing BVH nodes");
	pack_nodes(root);

	/* free build nodes */
	root->deleteSubtree();
}
Example #3
0
BVHNode* BVHBuild::run()
{
	BVHRange root;

	/* add references */
	add_references(root);

	if(progress.get_cancel())
		return NULL;

	/* init spatial splits */
	if(params.top_level) /* todo: get rid of this */
		params.use_spatial_split = false;

	spatial_min_overlap = root.bounds().safe_area() * params.spatial_split_alpha;
	spatial_right_bounds.clear();
	spatial_right_bounds.resize(max(root.size(), (int)BVHParams::NUM_SPATIAL_BINS) - 1);

	/* init progress updates */
	progress_start_time = time_dt();
	progress_count = 0;
	progress_total = references.size();
	progress_original_total = progress_total;

	prim_segment.resize(references.size());
	prim_index.resize(references.size());
	prim_object.resize(references.size());

	/* build recursively */
	BVHNode *rootnode;

	if(params.use_spatial_split) {
		/* singlethreaded spatial split build */
		rootnode = build_node(root, 0);
	}
	else {
		/* multithreaded binning build */
		BVHObjectBinning rootbin(root, (references.size())? &references[0]: NULL);
		rootnode = build_node(rootbin, 0);
		task_pool.wait_work();
	}

	/* delete if we canceled */
	if(rootnode) {
		if(progress.get_cancel()) {
			rootnode->deleteSubtree();
			rootnode = NULL;
		}
		else if(!params.use_spatial_split) {
			/*rotate(rootnode, 4, 5);*/
			rootnode->update_visibility();
		}
	}

	return rootnode;
}
Example #4
0
//--------------------------------------------------------------
// return count of descendents
int BVHNode::nodeCount()
{
  int count = 1;
  for (int i = 0; i < m_children.length(); i++)
  {
    BVHNode* child = (BVHNode*) m_children[i];
    count += child->nodeCount();
  }
  return count;
}
Example #5
0
float BVHNode::computeSubtreeSAHCost(const BVHParams& p, float probability) const
{
	float SAH = probability * p.cost(num_children(), num_triangles());

	for(int i = 0; i < num_children(); i++) {
		BVHNode *child = get_child(i);
		SAH += child->computeSubtreeSAHCost(p, probability * child->bounds.safe_area()/bounds.safe_area());
	}

	return SAH;
}
void PhotonAccelerator::build(const std::vector<Hitpoint*>& hitpoints)
{
	hps = hitpoints;
	nodes.reserve(2 * hitpoints.size() - 1);
	BVHNode root;
	AABB& world_box = root.getAABB();
	std::for_each(hps.begin(), hps.end(), [&] (Hitpoint* hp) {
		AABB aabb(hp->is.mPosition);
		aabb.grow(hp->radius);
		world_box.include(aabb);
	});
	nodes.push_back(root);
	build_recursive(0, hps.size(), &nodes[0], 0);
}
Example #7
0
void IKTree::reset(int frame)
{
  MT_Quaternion q;
  BVHNode *n;

  for (int i=0; i<numBones; i++) {
    bone[i].pos = origin;
    bone[i].lRot = identity;
    bone[i].gRot = identity;
    n = bone[i].node;
    Rotation rot=n->frameData(frame).rotation();
    Position pos=n->frameData(frame).position();

    for (int k=0; k<n->numChannels; k++) {  // rotate each axis in order
      q = identity;
      switch (n->channelType[k]) {
      case BVH_XROT:
        q.setRotation(xAxis, rot.x * M_PI / 180);
      break;
      case BVH_YROT:
        q.setRotation(yAxis, rot.y * M_PI / 180);
      break;
      case BVH_ZROT:
        q.setRotation(zAxis, rot.z * M_PI / 180);
      break;
      case BVH_XPOS: bone[i].pos[0] = pos.x; break;
      case BVH_YPOS: bone[i].pos[1] = pos.y; break;
      case BVH_ZPOS: bone[i].pos[2] = pos.z; break;
      }
      bone[i].lRot = q * bone[i].lRot;
    }
/*
    for (int k=0; k<3; k++) {  // rotate each axis in order
      rad = n->frame[frame][k] * M_PI / 180;
      q = identity;
      switch (n->channelType[k]) {
      case BVH_XROT: q.setRotation(xAxis, rad); break;
      case BVH_YROT: q.setRotation(yAxis, rad); break;
      case BVH_ZROT: q.setRotation(zAxis, rad); break;
      case BVH_XPOS: bone[i].pos[0] = n->frame[frame][k]; break;
      case BVH_YPOS: bone[i].pos[1] = n->frame[frame][k]; break;
      case BVH_ZPOS: bone[i].pos[2] = n->frame[frame][k]; break;
      }
      bone[i].lRot = q * bone[i].lRot;
    }
*/
  }
  updateBones(0);
}
Example #8
0
	vec3 raycolor(const ray& r, hitrecord& hr, int depth = 0)
	{
		if (depth > depth_count) return vec3(0, 0, 0);
		ray_count++;
		if (scene->hit(r, hr))
		{
			//return vec3(1);
			if (hr.p->mat()->emit.sqrlength() > 0)
				return hr.p->mat()->emit;
			//	vec3 rd = cosdistrib(hr.norm);
			hitrecord hrr;
			hrr.t = 1000000;
			vec3 c = vec3(0);// (hr.p->mat()->diffuse * raycolor(ray(r.e + ((hr.t - 0.01f)*r.d), rd), hrr, depth + 1));
			vec3 dt = hr.p->mat()->diffuse * (hr.p->mat()->tex != nullptr ? hr.p->mat()->tex->Texel(hr.textureCoord) : vec3(1));
		//	for (float i = 0; i < bounce_count; ++i)
		//	{
			vec3 v =  (dt * raycolor(ray(r.e + ((hr.t - 0.01f)*r.d), cosdistrib(hr.norm)), hrr, depth + 1));
				return v;
				//c = c + v;
		//	}
		//	c = c * (1.f / bounce_count);
			return c;
		}
		else
		{
			vec3 v = vec3(0.2f, 0.2f, 0.2f);// +(r.d.dot(vec3(0, 1, 0))*vec3(0, 0.3f, 1));
			//v.x = 0;
			return v;
		}
	}
Example #9
0
inline float Exhaustive(const Ray charles, float t, const BVHNode& node, 
                        const vector<Sphere> spheres, unsigned int &sphereId) {

    exhaustives += node.GetPrimitiveRange();

    for (unsigned int p = node.GetFirstPrimitive(); 
         p < node.GetFirstPrimitive() + node.GetPrimitiveRange(); ++p) {

        const Sphere sphere = spheres[p];
        const float tSphere = sphere.Intersect(charles);
        if (0 < tSphere && tSphere < t) {
            sphereId = p;
            t = tSphere;
        }
    }

    return t;
}
Example #10
0
/**
 * Output
 */
std::string BVHNode::toString() const {
	using std::stringstream;
	using std::endl;

	stringstream ss;
	ss << "\t" << id << " [width=.5,height=1,style=filled,color=\".5 .5 .5\",shape=box,label=\"" << id << ",\\n" << box.min << ",\\n" << box.max << "\"];" << std::endl;
	if (leaf) {
		for(uint i = 0; i < 2; ++i) {
			Object* o = childs[i].leaf;
			if (o) ss << "\t" << id << " -> " << "box" << o->id << std::endl << o->toString();
		}
		ss << std::endl;
	} else {
		for(uint i = 0; i < 2; ++i) {
			BVHNode* o = childs[i].node;
			ss << "\t" << id << " -> " << o->id << std::endl << o->toString();
		}
		ss << std::endl;
	}
	return ss.str();
}
Example #11
0
void IKTree::solve(int frame)
{
  double x, y, z;
  reset(frame);

  IKEffectorList effList;

  for (int i=0; i<20; i++) {
    effList.num = 0;
    solveJoint(frame, 0, effList);
  }

  for (int i=0; i<numBones-1; i++) {
    BVHNode *n = bone[i].node;
    Rotation rot=n->frameData(frame).rotation();
    toEuler(bone[i].lRot, n->channelOrder, x, y, z);

    for (int j=0; j<n->numChannels; j++) {  // rotate each axis in order
      switch (n->channelType[j]) {
        case BVH_XROT: n->ikRot.x = x - rot.x; break;
        case BVH_YROT: n->ikRot.y = y - rot.y; break;
        case BVH_ZROT: n->ikRot.z = z - rot.z; break;
        default: break;
      }
    }

/*
    for (int j=0; j<3; j++) {  // rotate each axis in order
      switch (n->channelType[j]) {
        case BVH_XROT: n->ikRot[j] = x - n->frame[frame][j]; break;
        case BVH_YROT: n->ikRot[j] = y - n->frame[frame][j]; break;
        case BVH_ZROT: n->ikRot[j] = z - n->frame[frame][j]; break;
        default: break;
      }
    } */
  }
  display = 1;
  updateBones(0);
  display = 0;
}
Example #12
0
/**
 * Iteratively intersect rays with the given nodes and returns the distance to
 * the closest intersection and stores the id of the intersected sphere in
 * sphereId.
 */
inline float ItrIntersect(const Ray charles, const vector<BVHNode>& nodes, 
                          const vector<Sphere> spheres, unsigned int &sphereId) {
    
    // cout << "=== ItrIntersect:" << charles.ToString() << " ===" << endl;
    
    sphereId = -1;
    float t = 1e30f;
    vector<std::pair<int, float> > stack(60);
    int i = 0;
    stack[i] = std::pair<int, float>(0, 0.0f);

    do {
        // cout << "\n----" << endl;
        // for (int j = i; j >= 0; --j)
        //     cout << "| " << j << ": " << stack[j].second << " - " << nodes[stack[j].first].ToString() << endl;
        // cout << "----" << endl;

        std::pair<int, float> next = stack[i]; --i;
        if (t < next.second) {
            // cout << i << "discard: " << nodes[next.first].ToString() << endl;
            continue;
        }
        
        BVHNode currentNode = nodes[next.first];

        if (currentNode.GetType() == BVHNode::LEAF) // Intersect leaf
            t = Exhaustive(charles, t, currentNode, spheres, sphereId);
        else {
            rayAABBCheck += 2;
        
            const BVHNode& left = nodes[currentNode.GetLeftChild()];
            float tLeft;
            if (!left.aabb.ClosestIntersection(charles, tLeft)) tLeft = 1e32f;
            
            const BVHNode& right = nodes[currentNode.GetRightChild()];
            float tRight;
            if (!right.aabb.ClosestIntersection(charles, tRight)) tRight = 1e32f;

            if (tLeft < tRight) { // Intersect left first
                if (tRight < t) stack[++i] = std::pair<int, float>(currentNode.GetRightChild(), tRight);
                if (tLeft < t) stack[++i] = std::pair<int, float>(currentNode.GetLeftChild(), tLeft);
            } else { // Intersect right first
                if (tLeft < t) stack[++i] = std::pair<int, float>(currentNode.GetLeftChild(), tLeft);
                if (tRight < t) stack[++i] = std::pair<int, float>(currentNode.GetRightChild(), tRight);
            }
        }
    } while (i >= 0);

    return t;
}
Example #13
0
BVHNode * BVHTree::buildSubTree(std::vector<Shape *> shapes, int depth) {
    int size = (int) shapes.size();
    int axis = depth % dims; // 0-2

    // Construct leaf BVHNode containing shapes
    if (size == shapesPerLeaf) {
        BVHNode *leaf = new BVHNode();
        leaf->addShape(shapes[0]); // Add shape and init bbox
        leaf->leaf = true;
        return leaf;
    } else if (size == 0) {
        return NULL;
    }
    // Otherwise split the shapes into two subsets, and divide them amongst
    // the left and right child nodes

    // Sort shapes based on the current axis
    std::sort(shapes.begin(), shapes.end(), comparators[axis]);

    // Find the median 
    int median = size / 2;
    std::vector<Shape *>::iterator mid = shapes.begin() + median;

    // Construct tree BVHNode
    BVHNode *treeNode = new BVHNode();

    // Construct left child BVHNode
    std::vector<Shape *> lShapes(shapes.begin(), mid);
    treeNode->left = buildSubTree(lShapes, depth + 1);

    // Construct right child BVHNode
    std::vector<Shape *> rShapes(mid, shapes.end());
    treeNode->right = buildSubTree(rShapes, depth + 1);

    // Store the bbox for the treeNode
    treeNode->bbox = treeNode->left->bbox + treeNode->right->bbox;
    return treeNode;
}
void PhotonAccelerator::accumulate(const Intersection& is, Color flux)
{
	BVHNode* currentNode = &nodes[0];
	AABB& box = currentNode->getAABB();
	Point3D point = is.mPosition;
	if (!box.inside(point))
		return;
	std::stack<BVHNode> intersect_stack;
	while (true) {
		if (currentNode->isLeaf()) {
			Vector3D v(point);
			for (unsigned int i = currentNode->getIndex(); i < currentNode->getIndex() + currentNode->getNObjs(); ++i) {
				Hitpoint& hp = *hps[i];
				if ((v - hp.is.mPosition).length() <= hp.radius && hp.is.mNormal * is.mNormal >= 0) {
					hp.newPhotonCount += 1;
					hp.totalFlux += flux * hp.is.mMaterial->evalBRDF(hp.is, -is.mRay.dir);
				}
			}
		} else {
			BVHNode& left_node = nodes[currentNode->getIndex()];
			BVHNode& right_node = nodes[currentNode->getIndex() + 1];
			AABB& left_box = left_node.getAABB();
			AABB& right_box = right_node.getAABB();

			bool leftHit, rightHit;
			leftHit = left_box.inside(point);
			rightHit = right_box.inside(point);
			if (leftHit && rightHit) {
				currentNode = &left_node;
				intersect_stack.push(right_node);
				continue;
			} else if (leftHit) {
				currentNode = &left_node;
				continue;
			} else if (rightHit) {
				currentNode = &right_node;
				continue;
			}
		}
		if (intersect_stack.empty())
			return;
		currentNode = &intersect_stack.top();
		intersect_stack.pop();
	}
}
BVHNode* BVH::RecursiveBuild(uint32_t start, uint32_t end, uint32_t depth)
{
    maxDepth = fmaxf(depth, maxDepth);
    totalNodes++;
    BVHNode* node = new BVHNode;

    //compute bounds of all primitives in BVH node
    BBox bbox;
    for(auto i = start; i < end; ++i)
        bbox = Union(bbox, workList[i].bounds);

    uint32_t nPrims = end - start;
    //if number of primitives are less than threshold, create leaf node
    if(nPrims <= MAX_LEAF_PRIM_NUM)
    {
        uint32_t firstPrimOffset = orderedPrims.size();
        for(auto i = start; i < end; ++i)
        {
            auto pIdx = workList[i].pIdx;
            orderedPrims.push_back(mesh.faces[pIdx]);
        }
        node->InitLeaf(firstPrimOffset, nPrims, bbox);
    }
    else
    {
        //compute bound of primitive centroids, choose split dimension
        BBox centroidBounds;
        for(auto i = start; i < end; ++i)
            centroidBounds = Union(centroidBounds, workList[i].bounds.bcenter);

        // split along max span axis
        int dim = centroidBounds.MaxExtent();

        //partition primitives into two sets and build children
        uint32_t mid = (end + start) / 2;
        // if max span axis is too small, create a leaf node
        if((centroidBounds.bmax[dim] - centroidBounds.bmin[dim]) < 1e-4)
        {
            uint32_t firstPrimOffset = orderedPrims.size();
            for(auto i = start; i < end; ++i)
            {
                auto pIdx = workList[i].pIdx;
                orderedPrims.push_back(mesh.faces[pIdx]);
            }
            node->InitLeaf(firstPrimOffset, nPrims, bbox);

            return node;
        }

        //partition primitives based on SAH
        std::vector<BucketInfo> buckets(nBuckets);
        float extent = centroidBounds.bmax[dim] - centroidBounds.bmin[dim];
        for(auto i = start; i < end; ++i)
        {
            uint32_t b = nBuckets * ((workList[i].bounds.bcenter[dim] - centroidBounds.bmin[dim]) / extent);
            if(b == nBuckets) b -= 1;
            buckets[b].count++;
            buckets[b].bounds = Union(buckets[b].bounds, workList[i].bounds);
        }

        //compute costs for splitting after each bucket
        float cost[nBuckets - 1];
        for(auto i = 0; i < nBuckets - 1; ++i)
        {
            BBox b0, b1;
            int count0 = 0, count1 = 0;

            for(auto j = 0; j <= i; ++j)
            {
                b0 = Union(b0, buckets[j].bounds);
                count0 += buckets[j].count;
            }
            for(auto j = i + 1; j < nBuckets; ++j)
            {
                b1 = Union(b1, buckets[j].bounds);
                count1 += buckets[j].count;
            }

            cost[i] = (count0 * b0.SurfaceArea() + count1 * b1.SurfaceArea()) / bbox.SurfaceArea();
        }

        //find best split
        float minCost = cost[0];
        uint32_t bestSplit = 0;
        for(auto i = 1; i < nBuckets - 1; ++i)
        {
            if(cost[i] < minCost)
            {
                minCost = cost[i];
                bestSplit = i;
            }
        }

        //either create leaf or split at selected SAH bucket
        if(nPrims > MAX_LEAF_PRIM_NUM || minCost < nPrims)
        {
            auto compare = [&](BVHPrimitiveInfo& p) {
                auto b = nBuckets * ((p.bounds.bcenter[dim] - centroidBounds.bmin[dim]) / extent);
                b = (b == nBuckets) ? (b - 1) : b;
                return b <= bestSplit;
            };
            BVHPrimitiveInfo *pmid = std::partition(&workList[start], &workList[end - 1] + 1, compare);
            mid = pmid - &workList[0];
        }
        else
        {
            uint32_t firstPrimOffset = orderedPrims.size();
            for(auto i = start; i < end; ++i)
            {
                auto pIdx = workList[i].pIdx;
                orderedPrims.push_back(mesh.faces[pIdx]);
            }
            node->InitLeaf(firstPrimOffset, nPrims, bbox);

            return node;
        }

        node->InitInner(RecursiveBuild(start, mid, depth + 1), RecursiveBuild(mid, end, depth + 1));
    }

    return node;
}
Example #16
0
void Blender::EvaluateRelativeLimbWeights(QList<TimelineTrail*>* trails, int trailsCount)       //TODO: into below method?
{
  int minPosIndex = 999999999;
  int maxPosIndex = -1;
  TrailItem** currentItems = new TrailItem*[trailsCount];

  //Find first and last occupied time-line position. And initialize currentItems with first non-shadows
  for(int i=0; i<trailsCount; i++)
  {
    TrailItem* firstItem = trails->at(i)->firstItem();
    if(firstItem==NULL)
    {
      currentItems[i] = NULL;
      continue;
    }

    //Shadow items don't matter much because the nearest/furthest item is always non-shadow
    if(firstItem->beginIndex() < minPosIndex)
      minPosIndex = firstItem->beginIndex();

    TrailItem* lastItem = trails->at(i)->lastItem();
    if(lastItem->endIndex() > maxPosIndex)
      maxPosIndex = trails->at(i)->lastItem()->endIndex();

    while(firstItem->isShadow())
      firstItem = firstItem->nextItem();
    currentItems[i] = firstItem;
  }
  if(maxPosIndex == -1)                       //Time-line is empty
    return;

  int curPosIndex = minPosIndex;
  //Position pseudo-node is not included, but it's OK as it can't be highlighted
  QStringList boneNames = BVH::getValidNodeNames();
  while(curPosIndex<=maxPosIndex)
  {
    foreach(QString bName, boneNames)
    {
      int sumWeight = 0;
      int weightsUsed = 0;
      bool emptyPosition = true;

      //Temporary helper structure. Value is array of 2 integers: frame index inside
      //respective animation and its frame weight
      QMap<BVHNode*, QVector<int> >* usedData = new QMap<BVHNode*, QVector<int> >();

      for(int i=0; i<trailsCount; i++)
      {
        TrailItem* item = currentItems[i];

        if(item == NULL)                                 //No more items on i-th trail
          continue;
        if(item->beginIndex() > curPosIndex)             //We're before first item of this trail
          continue;

        if(item->endIndex() < curPosIndex)               //Move to next item
        {
          currentItems[i] = item->nextItem();
          item = currentItems[i];
        }
        if(item == NULL || item->isShadow())             //Still here?
          continue;
        else
          emptyPosition = false;

        if(item->beginIndex() <= curPosIndex && item->endIndex() >= curPosIndex)
        {
          int frameIndex = curPosIndex - item->beginIndex();
          int frameWeight = item->getWeight(frameIndex);

          if(!item->getAnimation()->bones()->contains(bName))
            Announcer::Exception(NULL, "Exception: can't evaluate relative weight for limb " +bName);


//          BVHNode* limb = item->getAnimation()->bones()->value(bName);      NOT WORKING. REALLY NEED TO KNOW WHY
          //desperate DEBUG
          BVHNode* limb = item->getAnimation()->getNodeByName(bName);

          QVector<int> tempData;
          tempData << frameIndex << frameWeight;
          usedData->insert(limb, tempData);
          sumWeight += frameWeight * limb->frameData(frameIndex).weight();
          weightsUsed++;
        }
//        else Announcer::Exception(NULL, "Lame programmer exception :(");    //DEBUG
      }

      if(emptyPosition)                         //There were no valid item at this position
        break;                                  //so jump to the next one



      QMapIterator<BVHNode*, QVector<int> > iter(*usedData);
      while(iter.hasNext())
      {
        iter.next();
        BVHNode* bone = iter.key();
        QVector<int> tempData = iter.value();
        int frame = tempData[0];
        int frameW = tempData[1];

        if(sumWeight==0)                        //Little trick if weight of current limb was 0 on all trails
          bone->setKeyFrameRelWeight(frame, 1.0 / (double)weightsUsed);
        else
        {
          int limbW = bone->frameData(frame).weight();
          double relWei = (double)(frameW*limbW) / (double)sumWeight;
          bone->setKeyFrameRelWeight(frame, relWei);
        }
      }

      delete usedData;
    }
    curPosIndex++;
  }
Example #17
0
	int encodeIdx() const
	{
		return (node->is_leaf())? ~idx: idx;
	}
Example #18
0
BVHNode *BVHParser::parseNode( Buffer & buf, BVHNode * parent )
{
	BVHNode * node = new BVHNode();
	node->parent = parent;
	
	_linearNodes.push_back(node);
	
	buf.getToken(node->name);
	
	std::string str;
	
	buf.getToken(str);
	if( str != "{" )
	{
		debugPrint("Error didnt find opening bracket\n");
		delete node;
		return 0;
	}
	
	// parse offset
	buf.getToken(str);
	if(str!="OFFSET")
	{
		debugPrint("Error didnt find OFFSET\n");
		delete node;
		return 0;
	}
	
	buf.readLine(str);
	
	sscanf(str.c_str(),"%f %f %f",&node->offset.x,&node->offset.y,&node->offset.z);
	
	//buf.getToken(str);
	if(!buf.testToken("CHANNELS"))//, <#bool caseSensitive#>)str!="CHANNELS")
	{
		debugPrint("Error didnt find CHANNELS\n");
		delete node;
		return 0;
	}

	// parse channels 
	
	int nChannels = 0;
	
	buf.readInt(&nChannels);
	
	for( int i = 0; i < nChannels; i++ )
	{
		buf.getToken(str);
		BVH_CHANNEL chan = parseChannel(str);
		if(chan == CHANNEL_UNKNOWN) 
		{
			debugPrint("Error undefined channel %s\n",str.c_str());
			delete node;
			return 0;
		}
		node->channels.push_back(chan);
	}
	
	buf.getToken(str);
	
	// parse children ( if any... )
	while( str!="}" )
	{
		if( str=="JOINT" )
		{
			BVHNode * child = parseNode(buf,node);
			if(child==0)
			{
				debugPrint("Could not add child\n");
				delete node;
				return 0;
			}
			
			node->addChild(child);
			//buf.getToken(str);
		}
		else if( str=="End" )
		{
			buf.getToken(str); // skip site
			
			BVHNode * child = parseEndSite(buf,node);
			if(child==0)
			{
				debugPrint("Could not add child\n");
				delete node;
				return 0;
			}
			
			node->addChild(child);
		}
		
		buf.getToken(str);
	}
	
	// Hacky compute bone length...
	if( node->children.size() )
	{
		BVHNode * child = node->children[0];
	}
		
	return node;
}
Example #19
0
    BVHNode* BVH::buildRecursive(std::vector<BVHPrimitive> & data, unsigned start, unsigned end,
        std::vector<Face*> & orderedPrimitives, unsigned & totalNodes)
    {
        // Primitives in this branch
        const unsigned nPrimitives = end - start;

        // Allocate node (TODO: get from pool)
        BVHNode *node = new BVHNode;
        totalNodes++;

        // Calculate bounding box for all primitives given
        glm::aabb bounds;
        for(unsigned i = start; i < end; ++i)
            bounds = glm::aabb::combine(bounds, data[i].bounds);

        if(nPrimitives <= m_primitivesPerNode) // only n primitive left, create leaf node
        {
            const unsigned firstPrimitive = (unsigned)orderedPrimitives.size();
            for(unsigned i = start; i < end; ++i)
            {
                const unsigned primitive = data[i].primitive;
                orderedPrimitives.push_back(&mesh->faces[primitive]);
            }
            node->createLeaf(firstPrimitive, nPrimitives, bounds);
        }
        else
        {
            // Choose split dimension based on aabb centroids
            glm::aabb centroidBounds;
            for(unsigned i = start; i < end; ++i)
                centroidBounds.expand(data[i].centroid);
            if(centroidBounds.empty())
            {
                // All centroids the same, just create a leaf node

                const unsigned firstPrimitive = (unsigned)orderedPrimitives.size();
                for(unsigned i = start; i < end; ++i)
                {
                    const unsigned primitive = data[i].primitive;
                    orderedPrimitives.push_back(&mesh->faces[primitive]);
                }
                node->createLeaf(firstPrimitive, nPrimitives, bounds);

                return node;
            }

            const int dim = centroidBounds.largest_axis();                

            // Partition primitives to two subtrees
            const unsigned mid = (start + end) / 2;
            std::nth_element(&data[start], &data[mid], &data[end-1]+1,
                [=] (const BVHPrimitive & a, const BVHPrimitive & b)
                {
                    return a.centroid[dim] < b.centroid[dim];
                });

            node->createInterior(dim,
                buildRecursive(data, start, mid, orderedPrimitives, totalNodes),
                buildRecursive(data, mid, end, orderedPrimitives, totalNodes));
        }

        return node;
    }
Example #20
0
CCL_NAMESPACE_BEGIN

/* BVH Node */

int BVHNode::getSubtreeSize(BVH_STAT stat) const
{
	int cnt = 0;

	switch(stat)
	{
		case BVH_STAT_NODE_COUNT:
			cnt = 1;
			break;
		case BVH_STAT_LEAF_COUNT:
			cnt = is_leaf() ? 1 : 0;
			break;
		case BVH_STAT_INNER_COUNT:
			cnt = is_leaf() ? 0 : 1;
			break;
		case BVH_STAT_TRIANGLE_COUNT:
			cnt = is_leaf() ? reinterpret_cast<const LeafNode*>(this)->num_triangles() : 0;
			break;
		case BVH_STAT_CHILDNODE_COUNT:
			cnt = num_children();
			break;
		case BVH_STAT_QNODE_COUNT:
			cnt = 1;
			for(int i = 0; i < num_children(); i++) {
				BVHNode *node = get_child(i);
				if(node->is_leaf()) {
					cnt += 1;
				}
				else {
					for(int j = 0; j < node->num_children(); j++) {
						cnt += node->get_child(j)->getSubtreeSize(stat);
					}
				}
			}
			return cnt;
		case BVH_STAT_ALIGNED_COUNT:
			if(!is_unaligned) {
				cnt = 1;
			}
			break;
		case BVH_STAT_UNALIGNED_COUNT:
			if(is_unaligned) {
				cnt = 1;
			}
			break;
		case BVH_STAT_ALIGNED_INNER_COUNT:
			if(!is_leaf()) {
				bool has_unaligned = false;
				for(int j = 0; j < num_children(); j++) {
					has_unaligned |= get_child(j)->is_unaligned;
				}
				cnt += has_unaligned? 0: 1;
			}
			break;
		case BVH_STAT_UNALIGNED_INNER_COUNT:
			if(!is_leaf()) {
				bool has_unaligned = false;
				for(int j = 0; j < num_children(); j++) {
					has_unaligned |= get_child(j)->is_unaligned;
				}
				cnt += has_unaligned? 1: 0;
			}
			break;
		case BVH_STAT_ALIGNED_INNER_QNODE_COUNT:
			{
				bool has_unaligned = false;
				for(int i = 0; i < num_children(); i++) {
					BVHNode *node = get_child(i);
					if(node->is_leaf()) {
						has_unaligned |= node->is_unaligned;
					}
					else {
						for(int j = 0; j < node->num_children(); j++) {
							cnt += node->get_child(j)->getSubtreeSize(stat);
							has_unaligned |= node->get_child(j)->is_unaligned;
						}
					}
				}
				cnt += has_unaligned? 0: 1;
			}
			return cnt;
		case BVH_STAT_UNALIGNED_INNER_QNODE_COUNT:
			{
				bool has_unaligned = false;
				for(int i = 0; i < num_children(); i++) {
					BVHNode *node = get_child(i);
					if(node->is_leaf()) {
						has_unaligned |= node->is_unaligned;
					}
					else {
						for(int j = 0; j < node->num_children(); j++) {
							cnt += node->get_child(j)->getSubtreeSize(stat);
							has_unaligned |= node->get_child(j)->is_unaligned;
						}
					}
				}
				cnt += has_unaligned? 1: 0;
			}
			return cnt;
		case BVH_STAT_ALIGNED_LEAF_COUNT:
			cnt = (is_leaf() && !is_unaligned) ? 1 : 0;
			break;
		case BVH_STAT_UNALIGNED_LEAF_COUNT:
			cnt = (is_leaf() && is_unaligned) ? 1 : 0;
			break;
		case BVH_STAT_DEPTH:
			if(is_leaf()) {
				cnt = 1;
			}
			else {
				for(int i = 0; i < num_children(); i++) {
					cnt = max(cnt, get_child(i)->getSubtreeSize(stat));
				}
				cnt += 1;
			}
			return cnt;
		default:
			assert(0); /* unknown mode */
	}

	if(!is_leaf())
		for(int i = 0; i < num_children(); i++)
			cnt += get_child(i)->getSubtreeSize(stat);

	return cnt;
}