Example #1
0
void BvhTree::BuildNode(BvhNode *node, const std::list<Geom*> &a_geoms, int &outGeomPos)
{
	const int numGeoms = a_geoms.size();
	// make aabb from spheres
	// XXX suboptimal for static objects, as they have fixed rotation so
	// we can use a precise rotated aabb rather than worst case XXX
	Aabb aabb;
	aabb.min = vector3d(FLT_MAX, FLT_MAX, FLT_MAX);
	aabb.max = vector3d(-FLT_MAX, -FLT_MAX, -FLT_MAX);

	for (std::list<Geom*>::const_iterator i = a_geoms.begin();
			i != a_geoms.end(); ++i) {
		vector3d p = (*i)->GetPosition();
		double rad = (*i)->GetGeomTree()->GetRadius();
		aabb.Update(p + vector3d(rad,rad,rad));
		aabb.Update(p - vector3d(rad,rad,rad));
	}

	// divide by longest axis
	int axis;
	const vector3d axislen = aabb.max - aabb.min;
	if ((axislen.x > axislen.y) && (axislen.x > axislen.z)) axis = 0;
	else if (axislen.y > axislen.z) axis = 1;
	else axis = 2;
	const double pivot = 0.5*(aabb.max[axis] + aabb.min[axis]);

	std::list<Geom*> side[2];

	for (std::list<Geom*>::const_iterator i = a_geoms.begin();
			i != a_geoms.end(); ++i) {
		if ((*i)->GetPosition()[axis] < pivot) {
			side[0].push_back(*i);
		} else {
			side[1].push_back(*i);
		}
	}

	node->numGeoms = numGeoms;
	node->aabb = aabb;

	// side 1 has all nodes. just make a f*****g child
	if ((side[0].size() == 0) || (side[1].size() == 0)) {
		node->geomStart = &m_geoms[outGeomPos];

		// copy geoms to the stinking flat array
		for (std::list<Geom*>::const_iterator i = a_geoms.begin();
				i != a_geoms.end(); ++i) {
			m_geoms[outGeomPos++] = *i;
		}
	} else {
		// recurse!
		node->geomStart = 0;
		node->kids[0] = AllocNode();
		node->kids[1] = AllocNode();

		BuildNode(node->kids[0], side[0], outGeomPos);
		BuildNode(node->kids[1], side[1], outGeomPos);
	}
}
Example #2
0
void LightTree::build(const Assembly& assembly_) {
	assembly = &assembly_;

	// Populate the build nodes
	for (size_t i = 0; i < assembly->instances.size(); ++i) {
		const auto& instance = assembly->instances[i]; // Shorthand

		// If it's an object
		if (instance.type == Instance::OBJECT) {
			const Object* obj = assembly->objects[instance.data_index].get(); // Shorthand

			if (obj->total_emitted_color().energy() > 0.0f) {
				build_nodes.push_back(BuildNode());
				build_nodes.back().instance_index = i;
				build_nodes.back().bbox = assembly->instance_bounds_at(0.5f, i);
				build_nodes.back().center = build_nodes.back().bbox.center();
				const Vec3 scale = assembly->instance_xform_at(0.5f, i).get_inv_scale();
				const float surface_scale = ((scale[0]*scale[1]) + (scale[0]*scale[2]) + (scale[1]*scale[2])) * 0.33333333f;
				build_nodes.back().energy = obj->total_emitted_color().energy() / surface_scale;

				++total_lights;
			}
		}
		// If it's an assembly
		else if (instance.type == Instance::ASSEMBLY) {
			const Assembly* asmb = assembly->assemblies[instance.data_index].get(); // Shorthand
			const auto count = asmb->light_accel.light_count();
			const float energy = asmb->light_accel.total_emitted_color().energy();

			if (count > 0 && energy > 0.0f) {
				build_nodes.push_back(BuildNode());
				build_nodes.back().instance_index = i;
				if (instance.transform_count > 0) {
					auto xstart = assembly->xforms.cbegin() + instance.transform_index;
					auto xend = xstart + instance.transform_count;
					build_nodes.back().bbox = lerp_seq(0.5f, asmb->light_accel.bounds()).inverse_transformed(lerp_seq(0.5f, xstart, xend));
				} else {
					build_nodes.back().bbox = lerp_seq(0.5f, asmb->light_accel.bounds());
				}
				build_nodes.back().center = build_nodes.back().bbox.center();
				const Vec3 scale = assembly->instance_xform_at(0.5f, i).get_inv_scale();
				const float surface_scale = ((scale[0]*scale[1]) + (scale[0]*scale[2]) + (scale[1]*scale[2])) * 0.33333333f;
				build_nodes.back().energy = energy / surface_scale;

				total_lights += count;
			}
		}
	}

	if (build_nodes.size() > 0) {
		recursive_build(build_nodes.begin(), build_nodes.end());
		bounds_ = nodes[0].bounds;
		total_energy = nodes[0].energy;
	} else {
		bounds_.clear();
		bounds_.emplace_back(BBox());
	}
}
//----------------------------------------------------------------------------
PX2::Movable *SceneBuilder::BuildGeometry (INode *maxNode, PX2::Node *relatParent, bool hasSkin)
{
	// 建立并且链接几何图形物体到场景
	// maxNode:
	//		Max场景中节点的指针
	// relatParent:
	//		当前新节点要绑定到的父亲节点

	// 如果Max“几何图形”节点没有孩子节点,直接在relatParent下添加几何图形。
	// 如果Max“几何图形”节点有孩子节点,会新建一个Node节点,将孩子几何图形节
	// 点添加到这个新建的Node节点下。

	PX2::Movable *child = 0;
	PX2::Node *link = 0;

	int numMaxChildren = maxNode->NumberOfChildren();
	for (int i=0; i<numMaxChildren; i++)
	{
		ObjectState objectState = maxNode->GetChildNode(i)
			->EvalWorldState(mTimeStart);
		if (objectState.obj->SuperClassID() == GEOMOBJECT_CLASS_ID ||
			objectState.obj->SuperClassID() == HELPER_CLASS_ID)
		{
			link = BuildNode(maxNode, relatParent);
			break;
		}
	}

	if (link == 0)
	{
		if (mSettings->IncludeMeshes && !maxNode->IsHidden())
		{
			child = BuildMesh(maxNode, relatParent, hasSkin);
		}
		else
		{
			child = BuildNode(maxNode, relatParent);
		}

		return child;
	}
	else
	{
		if (mSettings->IncludeMeshes && !maxNode->IsHidden())
		{
			child = BuildMesh(maxNode, link, hasSkin);
		}
		else
		{
			child = BuildNode(maxNode, link);
		}

		return link;
	}
}
void KdTreeBuilder::BuildNode(const BoundingBox_f& nodeBounds,
                              const int32_t* nodeTriangles,
                              int32_t nodeTrianglesCount, int depth,
                              int32_t* triangles0, int32_t* triangles1)
{
  if (nodes.size() >= KdTree::Node::maxNodesCount)
    RuntimeError("maximum number of KdTree nodes has been reached: " +
                 std::to_string(KdTree::Node::maxNodesCount));

  // check if leaf node should be created
  if (nodeTrianglesCount <= buildParams.leafTrianglesLimit || depth == 0) {
    CreateLeaf(nodeTriangles, nodeTrianglesCount);
    buildStats.NewLeaf(nodeTrianglesCount, buildParams.maxDepth - depth);
    return;
  }

  // select split position
  auto split = SelectSplit(nodeBounds, nodeTriangles, nodeTrianglesCount);
  if (split.edge == -1) {
    CreateLeaf(nodeTriangles, nodeTrianglesCount);
    buildStats.NewLeaf(nodeTrianglesCount, buildParams.maxDepth - depth);
    return;
  }
  float splitPosition = edgesBuffer[split.edge].positionOnAxis;

  // classify triangles with respect to split
  int32_t n0 = 0;
  for (int32_t i = 0; i < split.edge; i++) {
    if (edgesBuffer[i].IsStart())
      triangles0[n0++] = edgesBuffer[i].GetTriangleIndex();
  }

  int32_t n1 = 0;
  for (int32_t i = split.edge + 1; i < 2 * nodeTrianglesCount; i++) {
    if (edgesBuffer[i].IsEnd())
      triangles1[n1++] = edgesBuffer[i].GetTriangleIndex();
  }

  // add interior node and recursively create children nodes
  auto thisNodeIndex = static_cast<int32_t>(nodes.size());
  nodes.push_back(KdTree::Node());

  BoundingBox_f bounds0 = nodeBounds;
  bounds0.maxPoint[split.axis] = splitPosition;
  BuildNode(bounds0, triangles0, n0, depth - 1, triangles0, triangles1 + n1);

  auto aboveChild = static_cast<int32_t>(nodes.size());
  nodes[thisNodeIndex].InitInteriorNode(split.axis, aboveChild, splitPosition);

  BoundingBox_f bounds1 = nodeBounds;
  bounds1.minPoint[split.axis] = splitPosition;
  BuildNode(bounds1, triangles1, n1, depth - 1, triangles0, triangles1);
}
Example #5
0
/*
 * Recursively builds the BVH starting at the given node with the given
 * first and last primitive indices (in bag).
 */
size_t BVH4::recursive_build(size_t parent, size_t first_prim, size_t last_prim)
{
	// Allocate the node
	const size_t me = build_nodes.size();
	build_nodes.push_back(BuildNode());


	build_nodes[me].flags = 0;
	build_nodes[me].parent_index = parent;

	if (first_prim == last_prim) {
		// Leaf node

		build_nodes[me].flags |= IS_LEAF;
		build_nodes[me].data = prim_bag[first_prim].data;

		// Copy bounding boxes
		build_nodes[me].bbox_index = build_bboxes.size();
		build_nodes[me].ts = prim_bag[first_prim].data->bounds().size();
		for (size_t i = 0; i < build_nodes[me].ts; i++)
			build_bboxes.push_back(prim_bag[first_prim].data->bounds()[i]);
	} else {
		// Not a leaf node

		// Create child nodes
		uint32_t split_index = split_primitives(first_prim, last_prim);
		const size_t child1i = recursive_build(me, first_prim, split_index);
		const size_t child2i = recursive_build(me, split_index+1, last_prim);

		build_nodes[me].child_index = child2i;


		// Calculate bounds
		build_nodes[me].bbox_index = build_bboxes.size();
		// If both children have same number of time samples
		if (build_nodes[child1i].ts == build_nodes[child2i].ts) {
			build_nodes[me].ts = build_nodes[child1i].ts;

			// Copy merged bounding boxes
			for (size_t i = 0; i < build_nodes[me].ts; i++) {
				build_bboxes.push_back(build_bboxes[build_nodes[child1i].bbox_index+i]);
				build_bboxes.back().merge_with(build_bboxes[build_nodes[child2i].bbox_index+i]);
			}

		}
		// If children have different number of time samples
		else {
			build_nodes[me].ts = 1;

			// Merge children's bboxes to get our bbox
			build_bboxes.push_back(build_bboxes[build_nodes[child1i].bbox_index]);
			for (size_t i = 1; i < build_nodes[child1i].ts; i++)
				build_bboxes.back().merge_with(build_bboxes[build_nodes[child1i].bbox_index+i]);
			for (size_t i = 0; i < build_nodes[child2i].ts; i++)
				build_bboxes.back().merge_with(build_bboxes[build_nodes[child2i].bbox_index+i]);
		}
	}

	return me;
}
Example #6
0
void kDOPTree::BuildTree( Vector<Trianglef>& pTriangleSoup, Vector<Vector3f>& pVertices )
{
    // Keep a copy of the vertices and triangles.
    mVertices.resize( pVertices.size() );
    for( UInt32 i = 0; i < pVertices.size(); i++ )
        mVertices[i] = pVertices[i];
            
    mTriangles.resize( pTriangleSoup.size() );
    for( UInt32 i = 0; i < pTriangleSoup.size(); i++ )
    {
        mTriangles[i].mIndices[0] = pTriangleSoup[i].mIndices[0];
        mTriangles[i].mIndices[1] = pTriangleSoup[i].mIndices[1];
        mTriangles[i].mIndices[2] = pTriangleSoup[i].mIndices[2];
    }
    
    mTrianglesCentroids.resize( pTriangleSoup.size() );

    // Find each triangle center.
    for( UInt32 i = 0; i < pTriangleSoup.size(); i++ )
    {
        mTrianglesCentroids[i]  = mVertices[mTriangles[i].mIndices[0]];
        mTrianglesCentroids[i] += mVertices[mTriangles[i].mIndices[1]];
        mTrianglesCentroids[i] += mVertices[mTriangles[i].mIndices[2]];
        mTrianglesCentroids[i] *= (1.0f / 3.0f);
    }

    mNumNodes  = 1;
    mNumLeaves = 0;
    mMaxDepth  = 0;
    mDepth     = 0;

    // Create the root node.
    kDOPNode* root = GD_NEW(kDOPNode, this, "Engine::Collision::kDOPTree");
    mNodes.push_back( root );
    
    // Insert the triangles indices in the root node list.
    root->mTriangleIndices.resize( pTriangleSoup.size() );
    for( UInt32 i = 0; i < pTriangleSoup.size(); i++ )
    {
        root->mTriangleIndices[i] = i;
    }

    // Recursively build kDOP tree.
    BuildNode( root );

    // No need to store centroids.
    mTrianglesCentroids.clear();

/*
#ifdef GD_DEBUG
    // 
    // Report memory usage
    UInt32 memUsage = 0;
    memUsage += (mNodes.size() * 4) + (mNodes.size() * sizeof(kDOPNode));
    memUsage += mVertices.size() * sizeof(mVertices[0]);
    memUsage += mTriangles.size() * sizeof(mTriangles[0]);
    printf( "kDOPTree mem usage = %08d bytes", memUsage );
#endif
*/
}
KdTree KdTreeBuilder::BuildTree()
{
  const auto trianglesCount = mesh.GetTrianglesCount();

  // initialize bounding boxes
  triangleBounds.resize(trianglesCount);
  BoundingBox_f meshBounds;

  for (auto i = 0; i < trianglesCount; i++) {
    triangleBounds[i] = mesh.GetTriangleBounds(i);
    meshBounds = BoundingBox_f::Union(meshBounds, triangleBounds[i]);
  }

  // initialize working memory
  edgesBuffer.resize(2 * trianglesCount);
  trianglesBuffer.resize(trianglesCount * (buildParams.maxDepth + 1));

  // fill triangle indices for root node
  for (auto i = 0; i < trianglesCount; i++)
    trianglesBuffer[i] = i;

  // recursively build all nodes
  BuildNode(meshBounds, trianglesBuffer.data(), trianglesCount,
            buildParams.maxDepth, trianglesBuffer.data(),
            trianglesBuffer.data() + trianglesCount);

  buildStats.FinalizeStats();
  return KdTree(std::move(nodes), std::move(triangleIndices), mesh);
}
Example #8
0
void kDOPTree::BuildNode( kDOPTree::kDOPNode* pNode )
{
    mDepth++;
    
    if( mDepth > mMaxDepth )
        mMaxDepth = mDepth;

    FindBoundingBox( pNode );

    // Test if we're creating a leaf or a node.
    if( pNode->mTriangleIndices.size() > 5 )
    {
        mNumNodes++;

        Float axisMean;
        Axis splitAxis = SelectSplitAxis( pNode->mTriangleIndices, axisMean );

        // Add two nodes.
        kDOPNode* leftNode  = GD_NEW(kDOPNode, this, "Engine::Collision::kDOPTree");
        kDOPNode* rightNode = GD_NEW(kDOPNode, this, "Engine::Collision::kDOPTree");

        pNode->mChildsIndex = mNodes.size();
        
        mNodes.push_back( leftNode );
        mNodes.push_back( rightNode );

        // Split triangles into two list.
        SplitTriangles( pNode, splitAxis, axisMean );

        // No need to store this in nodes.
        pNode->mTriangleIndices.clear();

        // Recursively call build tree.
        BuildNode( leftNode );
        BuildNode( rightNode );
    }
    else
    {
        // No work to do for leaves!
        mNumLeaves++;
    }

    mDepth--;
}
Example #9
0
BVHTree::BVHTree(int numObjs, const objPtr_t *objPtrs, const Aabb *objAabbs)
{
	std::vector<int> activeObjIdxs(numObjs);
	for (int i=0; i<numObjs; i++) activeObjIdxs[i] = i;

	m_objPtrAlloc = new objPtr_t[numObjs];
	m_objPtrAllocPos = 0;
	m_objPtrAllocMax = numObjs;

	m_bvhNodes = new BVHNode[numObjs*2 + 1];
	m_nodeAllocPos = 0;
	m_nodeAllocMax = numObjs*2 + 1;

	m_root = AllocNode();
	BuildNode(m_root, objPtrs, objAabbs, activeObjIdxs);
}
Example #10
0
int ESceneAIMapTool::AddNode(const Fvector& pos, bool bIgnoreConstraints, bool bAutoLink, int sz)
{
   	Fvector Pos				= pos;
    if (1==sz){
        SAINode* N 			= BuildNode(Pos,Pos,bIgnoreConstraints,true);
        if (N){
            N->flags.set	(SAINode::flSelected,TRUE);
            if (bAutoLink) 	UpdateLinks(N,bIgnoreConstraints);
            return			1;
        }else{
            ELog.Msg		(mtError,"Can't create node.");
            return 			0;
        }
    }else{
		return BuildNodes	(Pos,sz,bIgnoreConstraints);
    }
}
Example #11
0
BvhTree::BvhTree(const std::list<Geom*> &geoms)
{
	m_geoms = 0;
	m_nodesAlloc = 0;
	int numGeoms = geoms.size();
	if (numGeoms == 0) {
		m_root = 0;
		return;
	}
	m_geoms = new Geom*[numGeoms];
	int geomPos = 0;
	m_nodesAllocPos = 0;
	m_nodesAllocMax = numGeoms*2;
	m_nodesAlloc = new BvhNode[m_nodesAllocMax];
	m_root = AllocNode();
	BuildNode(m_root, geoms, geomPos);
	assert(geomPos == numGeoms);
}
//----------------------------------------------------------------------------
bool SceneBuilder::Traverse(INode *maxNode, PX2::Node *relatParent)
{
	// movbale对应maxNode的父节点

	bool isHasSkin = false;

	// Modifier
	if (mSettings->IncludeModifiers)
	{
		ModifierInfo *modInfo = new0 ModifierInfo;
		CollectModifiers(maxNode, modInfo->Modifiers);
		if (modInfo->Modifiers.empty())
		{
			delete0(modInfo);
		}
		else
		{
			modInfo->Node = maxNode;
			mModifierList.push_back(modInfo);

			for (int i=0; i<(int)modInfo->Modifiers.size(); i++)
			{
				Modifier *modifier = modInfo->Modifiers[i];
				Class_ID id = modifier->ClassID();
				if (id == SKIN_CLASSID ||
					id == Class_ID(PHYSIQUE_CLASS_ID_A, PHYSIQUE_CLASS_ID_B))
				{
					isHasSkin = true;
				}
			}
		}
	}

	// Node
	const char *nodeName = maxNode->GetName();

	if(stricmp(nodeName, "PHYSICSDATA") == 0)
	{
	}
	else if(stricmp(nodeName, "PORTALDATA") == 0)
	{
	}

	PX2::Movable *child = 0;

	ObjectState objectState = maxNode->EvalWorldState(mTimeStart);
	bool supported = true;

	// Object
	if (objectState.obj)
	{
		switch (objectState.obj->SuperClassID())
		{
		case GEOMOBJECT_CLASS_ID:
			if (IsNodeRenderable(maxNode, objectState.obj))
				child = BuildGeometry(maxNode, relatParent, isHasSkin);
			else
				child = BuildNode(maxNode, relatParent);
			break;
		case CAMERA_CLASS_ID:
			// ToDo
			break;
		case LIGHT_CLASS_ID:
			if (mSettings->IncludeLights && !maxNode->IsHidden())
			{
				BuildLight(maxNode, relatParent);
			}
			break;
		case HELPER_CLASS_ID:
			//supported = false;
			child = BuildNode(maxNode, relatParent);
			break;
		default:
			assertion(false, "Some object type not supportted.");
			supported = false;
			break;
		}
	}

	// Keyframe
	if (child)
	{
		if (mSettings->IncludeKeyFrames)
			BuildKeyFrameController(maxNode, child);
		else
			BuildFrameController(maxNode, child);
	}

	// Child
	int numChildren = maxNode->NumberOfChildren();
	if (numChildren == 0)
		return true;

	PX2::Node *childNode = 0;
	childNode = PX2::DynamicCast<PX2::Node>(child);
	if (childNode == 0)
		return true;

	for (int i=0; i<numChildren; i++)
	{
		if (!Traverse(maxNode->GetChildNode(i), childNode) || mMax->GetCancel())
			return false;
	}

	return true;
}
Example #13
0
void ESceneAIMapTool::BuildNodes(bool bFromSelectedOnly)
{
	// begin
	m_Nodes.reserve	(1024*1024);

	// Initialize hash
//	hash_Initialize ();

    R_ASSERT(!m_Nodes.empty());
    // Estimate nodes
    Fvector	Pos,LevelSize;
    m_AIBBox.getsize	(LevelSize);
    float estimated_nodes	= (LevelSize.x/m_Params.fPatchSize)*(LevelSize.z/m_Params.fPatchSize);

    SPBItem* pb = UI->ProgressStart(1, "Building nodes...");
    // General cycle
    for (int k=0; k<(int)m_Nodes.size(); k++){
        SAINode* N 			= m_Nodes[k];
    	if (bFromSelectedOnly && !N->flags.is(SAINode::flSelected)) continue;
        // left 
        if (0==N->n1){
            Pos.set			(N->Pos);
            Pos.x			-=	m_Params.fPatchSize;
            N->n1			=	BuildNode(N->Pos,Pos,false);
        }
        // fwd
        if (0==N->n2){
            Pos.set			(N->Pos);
            Pos.z			+=	m_Params.fPatchSize;
            N->n2			=	BuildNode(N->Pos,Pos,false);
        }
        // right
        if (0==N->n3){
            Pos.set			(N->Pos);
            Pos.x			+=	m_Params.fPatchSize;
            N->n3			=	BuildNode(N->Pos,Pos,false);
        }
        // back
        if (0==N->n4){
            Pos.set			(N->Pos);
            Pos.z			-=	m_Params.fPatchSize;
            N->n4			=	BuildNode(N->Pos,Pos,false);
        }
    	if (bFromSelectedOnly){
	        // select neighbour nodes
            if (N->n1) N->n1->flags.set(SAINode::flSelected,TRUE);
            if (N->n2) N->n2->flags.set(SAINode::flSelected,TRUE);
            if (N->n3) N->n3->flags.set(SAINode::flSelected,TRUE);
            if (N->n4) N->n4->flags.set(SAINode::flSelected,TRUE);
        }
        
        if (k%512==0) {
            float	p1	= float(k)/float(m_Nodes.size());
            float	p2	= float(m_Nodes.size())/estimated_nodes;
            float	p	= 0.1f*p1+0.9f*p2;

            clamp	(p,0.f,1.f);
            pb->Update(p);
            // check need abort && redraw
            if (k%32768==0) UI->RedrawScene(true);
            if (UI->NeedAbort()) break;
        }
    }
    UI->ProgressEnd(pb);
}
//----------------------------------------------------------------------------
PX2::Movable *SceneBuilder::BuildMesh(INode *maxNode,
									 PX2::Node *relatParentOrEqualNode)
{
	// 将Max的三角形网格数据转换到一个或者更多的等价的Phoenix2三角形网格。
	//
	// maxNode:
	//		Max场景图中的Mesh节点。
	// relatParentOrEqualNode:
	//		在Phoenix2场景图系统中最新创建的父亲节点。
	// 返回在Phoenix2场景中指向新的孩子节点的指针,这个指针直接指向TriMesh物体;
	// 或者是一个“link”节点,“link”的多个孩子TriMesh代表Max中的多个孩子mesh。

	bool needDel = false;
	TriObject *triObject = GetTriObject(maxNode, &needDel);
	if (!triObject)
	{
		return 0;
	}

	Mesh *maxMesh = &triObject->GetMesh();

	Mtl *mtl = maxNode->GetMtl();
	int mtlIndex = mMtls.GetIndex(mtl);

	// 判断这个Max的几何图形节点是否有“子几何图形节点”,如果有子几何图形节点
	// isEqualNode为真,反之为假。
	// 如果名称相等,就不是relatParentOrEqualNode了,而是equalNode
	PX2::Movable *link = 0;
	bool isEqualNode = (relatParentOrEqualNode->GetName().length()>0 &&
		strcmp(maxNode->GetName(), relatParentOrEqualNode->GetName().c_str()) == 0);

	// maxName
	char *maxName = maxNode->GetName();

	// 如果只需要一个Phoenix的Mesh表示Max的Mesh,直接将Phoenix的Mesh链接到
	// Phoenix的场景图中;否则,创建一个"link"节点,将按照材质分割的子Mesh
	// 放在"link"下。
	int i;
	std::vector<UniMaterialMesh*> uMeshs;
	SplitGeometry(maxMesh, mtlIndex, uMeshs);
	if ((int)uMeshs.size() > 1)
	{
		if (!isEqualNode)
		{
			link = BuildNode(maxNode, relatParentOrEqualNode);
		}
		else
		{
			link = relatParentOrEqualNode;
		}

		assertion(link->IsDerived(PX2::Node::TYPE), "link must be a Node.");

		for (i=0; i<(int)uMeshs.size(); i++)
		{
			PX2::TriMesh *triMesh = uMeshs[i]->ToTriMesh();

			if (triMesh)
			{
				char meshNumber[6];
				sprintf_s(meshNumber, 6, "_%d", i+1);
				size_t size = strlen(maxName) + strlen(meshNumber) + 1;
				char *tdName = new1<char>((int)size);
				strcpy_s(tdName, size, maxName);
				strcat_s(tdName, size, meshNumber);
				triMesh->SetName(tdName);
				delete1(tdName);
				((PX2::Node*)link)->AttachChild(triMesh);
			}
		}
	}
	else if ((int)uMeshs.size() == 1)
	{
		PX2::TriMesh *triMesh = uMeshs[0]->ToTriMesh();
		if (triMesh)
		{
			if (!isEqualNode)
			{
				triMesh->SetName(maxName);
				triMesh->LocalTransform = GetLocalTransform(maxNode, mTimeStart);
			}
			else
			{
				size_t size = strlen(maxName) + 3;
				char *tdName = new1<char>((int)size);
				strcpy_s(tdName, size, maxName);
				strcat_s(tdName, size, "_1");
				triMesh->SetName(tdName);
				delete1(tdName);
			}

			assertion(relatParentOrEqualNode->IsDerived(PX2::Node::TYPE), 
				"relatParentOrEqualNode must be a Node.");

			relatParentOrEqualNode->AttachChild(triMesh);
			link = triMesh;
		}
	}

	for (i=0; i<(int)uMeshs.size(); i++)
	{
		delete0(uMeshs[i]);
	}

	if (needDel)
	{
		delete0(triObject);
	}

	return link;
}
Example #15
0
CTreeNode* CTreeBuilder::AddNode(CTreeNode* pParentNode, NodeDetails enNodedetails)
{
	if (enNodedetails.type == STARTTAG || enNodedetails.type ==VALUE )
	{      
		CTreeNode* temp = BuildNode(enNodedetails); 
		CTreeNode*p = NULL;

		temp->SetParent(pParentNode); 

		if(temp->GetParent()== NULL)
		{	
			if(this->m_RootNode == NULL)
			{
				this->m_RootNode = temp;
			}
			else
			{
				p = this->m_RootNode;
				while(p && p->GetSibling()) 
					p = p->GetSibling();

				p->SetSibling(temp);
			}
		}
		else
		{
			if (pParentNode!=NULL) 
			{
				if(pParentNode->GetDepth()== temp->GetDepth()) /* sibling */
				{
					p = pParentNode->GetSibling();
					while(p && p->GetSibling()) 
						p = p->GetSibling();

					if(p)
						p->SetSibling(temp);
					else
						pParentNode->SetSibling(temp);
				}
				else
				{
					p = pParentNode->GetChild();
					while(p && p->GetSibling()) 
						p = p->GetSibling();

					if(p) 
						p->SetSibling(temp);
					else
						pParentNode->SetChild(temp);
				}
			}
		}

		if (enNodedetails.type != 2)
		{
			pParentNode = temp;
		}
		else
		{
			pParentNode = temp->GetParent();
		}

	} 
	if (enNodedetails.type == 1)
	{      
		if ( pParentNode->GetParent()!= NULL)
		{
			pParentNode = pParentNode->GetParent(); 
		}
	}
	return pParentNode;
}
Example #16
0
void BVHTree::BuildNode(BVHNode *node,
			const objPtr_t *objPtrs,
			const Aabb *objAabbs,
			std::vector<objPtr_t> &activeObjIdx)
{
	const int numTris = activeObjIdx.size();
	if (numTris <= 0) Error("BuildNode called with no elements in activeObjIndex.");

	if (numTris == 1) {
		MakeLeaf(node, objPtrs, activeObjIdx);
		return;
	}

	std::vector<int> splitSides(numTris);

	Aabb aabb;
	aabb.min = vector3d(FLT_MAX, FLT_MAX, FLT_MAX);
	aabb.max = vector3d(-FLT_MAX, -FLT_MAX, -FLT_MAX);

	for (int i=0; i<numTris; i++) {
		int idx = activeObjIdx[i];
		aabb.Update(objAabbs[idx].min);
		aabb.Update(objAabbs[idx].max);
	}
	node->numTris = numTris;
	node->aabb = aabb;

	Aabb splitBox = aabb;
	double splitPos;
	int splitAxis;
	int s1count, s2count;
	int attempt = 0;

	for (;;) {
		splitAxis = 0;

		vector3d boxSize = splitBox.max - splitBox.min;

		if (boxSize[1] > boxSize[0]) splitAxis = 1;
		if ((boxSize[2] > boxSize[1]) && (boxSize[2] > boxSize[0])) splitAxis = 2;

		// split pos in middle of splitBox
		splitPos = 0.5f * (splitBox.min[splitAxis] + splitBox.max[splitAxis]);
		s1count = 0, s2count = 0;

		for (int i=0; i<numTris; i++) {
			int idx = activeObjIdx[i];
			double mid = 0.5 * (objAabbs[idx].min[splitAxis] + objAabbs[idx].max[splitAxis]);
			if (mid < splitPos) {
				splitSides[i] = 0;
				s1count++;
			} else {
				splitSides[i] = 1;
				s2count++;
			}
		}

		if (s1count == numTris) {
			if (attempt < MAX_SPLITPOS_RETRIES) {
				// try splitting at average point
				splitBox.max[splitAxis] = splitPos;
				attempt++;
				continue;
			} else {
				MakeLeaf(node, objPtrs, activeObjIdx);
				return;
			}
		} else if (s2count == numTris) {
			if (attempt < MAX_SPLITPOS_RETRIES) {
				// try splitting at average point
				splitBox.min[splitAxis] = splitPos;
				attempt++;
				continue;
			} else {
				MakeLeaf(node, objPtrs, activeObjIdx);
				return;
			}
		}
		break;
	}

	std::vector<int> side[2];

	for (int i=0; i<numTris; i++) {
		side[splitSides[i]].push_back(activeObjIdx[i]);
	}

	// recurse!
	node->triIndicesStart = 0;
	node->kids[0] = AllocNode();
	node->kids[1] = AllocNode();

	BuildNode(node->kids[0], objPtrs, objAabbs, side[0]);
	BuildNode(node->kids[1], objPtrs, objAabbs, side[1]);
}
Example #17
0
void xrBuildNodes()
{
	// begin
	XRC.box_options	(CDB::OPT_FULL_TEST);
	XRC.ray_options	(CDB::OPT_CULL | CDB::OPT_ONLYNEAREST);
	g_nodes.reserve	(1024*1024);

	// Initialize hash
	hash_Initialize ();

	for (u32 em=0; em<Emitters.size(); em++) 
	{
		// Align emitter
		Fvector			Pos = Emitters[em];
		SnapXZ			(Pos);
		Pos.y			+=1;
		Fvector			Dir; Dir.set(0,-1,0);
		
		XRC.ray_query	(&Level,Pos,Dir,3);
		if (XRC.r_count()==0) {
			Msg		("Can't align emitter");
			abort	();
		} else {
			CDB::RESULT& R = *XRC.r_begin();
			Pos.y = Pos.y - R.range;
		}
		
		// Build first node
		int oldcount = g_nodes.size();
		int start = BuildNode		(Pos,Pos);
		if (start==InvalidNode)		continue;
		if (start<oldcount)			continue;

		// Estimate nodes
		Fvector	LevelSize;
		LevelBB.getsize				(LevelSize);
		u32	estimated_nodes		= iFloor(LevelSize.x/g_params.fPatchSize)*iFloor(LevelSize.z/g_params.fPatchSize);
		
		// General cycle
		for (u32 i=0; i<g_nodes.size(); i++)
		{
			// left 
			if (g_nodes[i].n1==UnkonnectedNode)
			{
				Pos.set			(g_nodes[i].Pos);
				Pos.x			-=	g_params.fPatchSize;
				int	id			=	BuildNode(g_nodes[i].Pos,Pos);
				g_nodes[i].n1	=	id;
			}
			// fwd
			if (g_nodes[i].n2==UnkonnectedNode)
			{
				Pos.set			(g_nodes[i].Pos);
				Pos.z			+=	g_params.fPatchSize;
				int id			=	BuildNode(g_nodes[i].Pos,Pos);
				g_nodes[i].n2	=	id;
			}
			// right
			if (g_nodes[i].n3==UnkonnectedNode)
			{
				Pos.set			(g_nodes[i].Pos);
				Pos.x			+=	g_params.fPatchSize;
				int id			=	BuildNode(g_nodes[i].Pos,Pos);
				g_nodes[i].n3	=	id;
			}
			// back
			if (g_nodes[i].n4==UnkonnectedNode)
			{
				Pos.set			(g_nodes[i].Pos);
				Pos.z			-=	g_params.fPatchSize;
				int	id			=	BuildNode(g_nodes[i].Pos,Pos);
				g_nodes[i].n4	=	id;
			}
			if (i%512==0) {
				Status("%d / %d nodes created.",g_nodes.size()-i,g_nodes.size());

				float	p1	= float(i)/float(g_nodes.size());
				float	p2	= float(g_nodes.size())/estimated_nodes;
				float	p	= 0.1f*p1+0.9f*p2;

				clamp	(p,0.f,1.f);
				Progress(p);
			}
		}
	}
	Msg("Freeing memory...");
	hash_Destroy	();
}
Example #18
0
int ESceneAIMapTool::BuildNodes(const Fvector& pos, int sz, bool bIC)
{
    // Align emitter
    Fvector			Pos = pos;
    SnapXZ			(Pos,m_Params.fPatchSize);
    Pos.y			+= 1;
    Fvector			Dir; Dir.set(0,-1,0);

	int cnt			= 0;		
    if (m_CFModel)
    	cnt=Scene->RayQuery(PQ,Pos,Dir,3,CDB::OPT_ONLYNEAREST|CDB::OPT_CULL,m_CFModel);
    else
    	cnt=Scene->RayQuery(PQ,Pos,Dir,3,CDB::OPT_ONLYNEAREST|CDB::OPT_CULL,GetSnapList());

    if (0==cnt) {
        ELog.Msg	(mtInformation,"Can't align position.");
        return		0;
    } else {
        Pos.y 		= Pos.y - PQ.r_begin()->range;
    }
		
    // Build first node
    int oldcount 	= m_Nodes.size();
    SAINode* start 	= BuildNode(Pos,Pos,bIC);
    if (!start)		return 0;

    // Estimate nodes
    float estimated_nodes	= (2*sz-1)*(2*sz-1);

	SPBItem* pb 	= 0;
    if (estimated_nodes>1024) pb = UI->ProgressStart(1, "Building nodes...");
    float radius			= sz*m_Params.fPatchSize-EPS_L;
    // General cycle
    for (int k=0; k<(int)m_Nodes.size(); k++){
        SAINode* N 			= m_Nodes[k];
        // left 
        if (0==N->n1){
            Pos.set			(N->Pos);
            Pos.x			-=	m_Params.fPatchSize;
            if (Pos.distance_to(start->Pos)<=radius)
	            N->n1		=	BuildNode(N->Pos,Pos,bIC);
        }
        // fwd
        if (0==N->n2){
            Pos.set			(N->Pos);
            Pos.z			+=	m_Params.fPatchSize;
            if (Pos.distance_to(start->Pos)<=radius)
	            N->n2		=	BuildNode(N->Pos,Pos,bIC);
        }
        // right
        if (0==N->n3){
            Pos.set			(N->Pos);
            Pos.x			+=	m_Params.fPatchSize;
            if (Pos.distance_to(start->Pos)<=radius)
	            N->n3		=	BuildNode(N->Pos,Pos,bIC);
        }
        // back
        if (0==N->n4){
            Pos.set			(N->Pos);
            Pos.z			-=	m_Params.fPatchSize;
            if (Pos.distance_to(start->Pos)<=radius)
	            N->n4		=	BuildNode(N->Pos,Pos,bIC);
        }
        if (estimated_nodes>1024){
            if (k%128==0) {
                float	p1	= float(k)/float(m_Nodes.size());
                float	p2	= float(m_Nodes.size())/estimated_nodes;
                float	p	= 0.1f*p1+0.9f*p2;

                clamp	(p,0.f,1.f);
                pb->Update(p);
                // check need abort && redraw
                if (UI->NeedAbort()) break;
            }
        }
    }
	if (estimated_nodes>1024) UI->ProgressEnd(pb);
    return oldcount-m_Nodes.size();
}