SwitchNode *SceneGraph::findSwitchNode(char *name) { if (!name || strlen(name) <= 0) return NULL; for (SwitchNode *node = findSwitchNode(); node; node = node->nextTraversal()) { const char *nodeName = node->getName(); if (nodeName && strlen(nodeName)) { if (!strcmp(name, nodeName)) return node; } } return NULL; }
//---------------------------------------------------------------------------- void Picker::ExecuteRecursive (Movable* object, bool &hasMeshPicked) { if (object) { if (!object->IsDoPick()) return; if (!object->IsShow() && !object->IsPickIngoreCullingMode()) return; } Triangles* mesh = DynamicCast<Triangles>(object); if (mesh) { if (!mesh->GetVertexBuffer()) return; if (mesh->WorldBound.TestIntersection(mOrigin, mDirection, mTMin, mTMax)) { if (mesh->IsUseBoundPick()) { AVector dir = mesh->GetWorldTransform().GetTranslate() - mOrigin; float length = dir.Length(); PickRecord record; record.Intersected = mesh; record.T = length; Records.push_back(record); } else { // 将射线从世界坐标系转换到模型坐标系。 APoint ptmp; if (!mesh->IsSkinCtrlSetWroldTrans) ptmp = mesh->WorldTransform.Inverse()*mOrigin; else ptmp = mesh->BoundWorldTransform.Inverse()*mOrigin; Vector3f modelOrigin(ptmp[0], ptmp[1], ptmp[2]); AVector vtmp; if (!mesh->IsSkinCtrlSetWroldTrans) vtmp = mesh->WorldTransform.Inverse()*mDirection; else vtmp = mesh->BoundWorldTransform.Inverse()*mDirection; Vector3f modelDirection(vtmp[0], vtmp[1], vtmp[2]); Line3f line(modelOrigin, modelDirection); // 访问方位数据 VertexBufferAccessor vba(mesh); int numTriangles = mesh->GetNumTriangles(); for (int i = 0; i < numTriangles; ++i) { int v0, v1, v2; if (!mesh->GetTriangle(i, v0, v1, v2)) { continue; } Vector3f vertex0 = vba.Position<Vector3f>(v0); Vector3f vertex1 = vba.Position<Vector3f>(v1); Vector3f vertex2 = vba.Position<Vector3f>(v2); Triangle3f triangle(vertex0, vertex1, vertex2); IntrLine3Triangle3f calc(line, triangle); if (calc.Find()) { float lineParameter = calc.GetLineParameter(); if (mTMin<=lineParameter && lineParameter<=mTMax) { PickRecord record; record.Intersected = mesh; record.T = calc.GetLineParameter(); record.Triangle = i; record.Bary[0] = calc.GetTriBary0(); record.Bary[1] = calc.GetTriBary1(); record.Bary[2] = calc.GetTriBary2(); Vector3f edg1 = vertex1 - vertex0; Vector3f edg2 = vertex2 - vertex0; Vector3f normal = edg1.UnitCross(edg2); float dotVal = line.Direction.Dot(normal); if (dotVal > Mathf::ZERO_TOLERANCE) { normal *= -1.0f; } record.LocalNormal = normal; record.WorldPos = mOrigin + mDirection * record.T; Records.push_back(record); if (mIsDoMovPickCall) { hasMeshPicked = true; mesh->OnPicked(mPickInfo); } } } } } } else { if (mIsDoMovPickCall) mesh->OnNotPicked(mPickInfo); } return; } SwitchNode* switchNode = DynamicCast<SwitchNode>(object); if (switchNode) { bool newHasChildPicked = false; int activeChild = switchNode->GetActiveChild(); if (activeChild != SwitchNode::SN_INVALID_CHILD) { if (switchNode->WorldBound.TestIntersection(mOrigin, mDirection, mTMin, mTMax)) { Movable* child = switchNode->GetChild(activeChild); if (child) { ExecuteRecursive(child, newHasChildPicked); } if (newHasChildPicked) { hasMeshPicked = true; } if (mIsDoMovPickCall) { if (hasMeshPicked) { switchNode->OnPicked(mPickInfo); } else { switchNode->OnNotPicked(mPickInfo); } } } else { if (mIsDoMovPickCall) switchNode->OnNotPicked(mPickInfo); } } return; } Node* node = DynamicCast<Node>(object); if (node) { bool newHasChildPicked = false; if (node->WorldBound.TestIntersection(mOrigin, mDirection, mTMin, mTMax)) { Movable *movPriority = 0; if (node->IsDoPickPriority()) { for (int i=0; i<node->GetNumChildren(); i++) { Movable *mov = node->GetChild(i); if (mov && mov->IsNotPickedParentChildrenNotPicked()) movPriority = mov; } } // 做优先检测 bool doLastPick = false; if (movPriority) { ExecuteRecursive (movPriority, doLastPick); } else { doLastPick = true; } if (doLastPick) { for (int i = 0; i < node->GetNumChildren(); ++i) { Movable* child = node->GetChild(i); if (child && child!=movPriority) { ExecuteRecursive(child, newHasChildPicked); } } if (newHasChildPicked) { hasMeshPicked = true; } if (mIsDoMovPickCall) { if (newHasChildPicked) { node->OnPicked(mPickInfo); } else { node->OnNotPicked(mPickInfo); } } } } else { if (mIsDoMovPickCall) node->OnNotPicked(mPickInfo); } } }
//---------------------------------------------------------------------------- void Picker::ExecuteRecursive (Movable* object, bool &hasMeshPicked) { if (object) { if (object->Culling == Movable::CULL_ALWAYS) return; } Triangles* mesh = DynamicCast<Triangles>(object); if (mesh) { if (mesh->WorldBound.TestIntersection(mOrigin, mDirection, mTMin, mTMax)) { // 将射线从世界坐标系转换到模型坐标系。 APoint ptmp = mesh->WorldTransform.Inverse()*mOrigin; Vector3f modelOrigin(ptmp[0], ptmp[1], ptmp[2]); AVector vtmp = mesh->WorldTransform.Inverse()*mDirection; Vector3f modelDirection(vtmp[0], vtmp[1], vtmp[2]); Line3f line(modelOrigin, modelDirection); // 访问方位数据 VertexBufferAccessor vba(mesh); int numTriangles = mesh->GetNumTriangles(); for (int i = 0; i < numTriangles; ++i) { int v0, v1, v2; if (!mesh->GetTriangle(i, v0, v1, v2)) { continue; } Vector3f vertex0 = vba.Position<Vector3f>(v0); Vector3f vertex1 = vba.Position<Vector3f>(v1); Vector3f vertex2 = vba.Position<Vector3f>(v2); Triangle3f triangle(vertex0, vertex1, vertex2); IntrLine3Triangle3f calc(line, triangle); if (calc.Find() && mTMin <= calc.GetLineParameter() && calc.GetLineParameter() <= mTMax) { PickRecord record; record.Intersected = mesh; record.T = calc.GetLineParameter(); record.Triangle = i; record.Bary[0] = calc.GetTriBary0(); record.Bary[1] = calc.GetTriBary1(); record.Bary[2] = calc.GetTriBary2(); Records.push_back(record); if (mIsDoMovPickCall) { hasMeshPicked = true; mesh->OnPicked(mPickInfo); } } } } else { if (mIsDoMovPickCall) mesh->OnNotPicked(mPickInfo); } return; } SwitchNode* switchNode = DynamicCast<SwitchNode>(object); if (switchNode) { int activeChild = switchNode->GetActiveChild(); if (activeChild != SwitchNode::SN_INVALID_CHILD) { if (switchNode->WorldBound.TestIntersection(mOrigin, mDirection, mTMin, mTMax)) { Movable* child = switchNode->GetChild(activeChild); if (child) { ExecuteRecursive(child, hasMeshPicked); } if (mIsDoMovPickCall) { if (hasMeshPicked) { switchNode->OnPicked(mPickInfo); } else { switchNode->OnNotPicked(mPickInfo); } } } else { if (mIsDoMovPickCall) switchNode->OnNotPicked(mPickInfo); } } return; } Node* node = DynamicCast<Node>(object); if (node) { if (node->WorldBound.TestIntersection(mOrigin, mDirection, mTMin, mTMax)) { for (int i = 0; i < node->GetNumChildren(); ++i) { Movable* child = node->GetChild(i); if (child) { ExecuteRecursive(child, hasMeshPicked); } } if (mIsDoMovPickCall) { if (hasMeshPicked) { node->OnPicked(mPickInfo); } else { node->OnNotPicked(mPickInfo); } } } else { if (mIsDoMovPickCall) node->OnNotPicked(mPickInfo); } } }
//---------------------------------------------------------------------------- void Picker::ExecuteRecursive (Spatial* object) { Triangles* mesh = DynamicCast<Triangles>(object); if (mesh) { if (mesh->WorldBound.TestIntersection(mOrigin, mDirection, mTMin, mTMax)) { // Convert the linear component to model-space coordinates. APoint ptmp = mesh->WorldTransform.Inverse()*mOrigin; Vector3f modelOrigin(ptmp[0], ptmp[1], ptmp[2]); AVector vtmp = mesh->WorldTransform.Inverse()*mDirection; Vector3f modelDirection(vtmp[0], vtmp[1], vtmp[2]); Line3f line(modelOrigin, modelDirection); // Get the position data. VertexBufferAccessor vba(mesh); // Compute intersections with the model-space triangles. int numTriangles = mesh->GetNumTriangles(); for (int i = 0; i < numTriangles; ++i) { int v0, v1, v2; if (!mesh->GetTriangle(i, v0, v1, v2)) { continue; } Vector3f vertex0 = vba.Position<Vector3f>(v0); Vector3f vertex1 = vba.Position<Vector3f>(v1); Vector3f vertex2 = vba.Position<Vector3f>(v2); Triangle3f triangle(vertex0, vertex1, vertex2); IntrLine3Triangle3f calc(line, triangle); if (calc.Find() && mTMin <= calc.GetLineParameter() && calc.GetLineParameter() <= mTMax) { PickRecord record; record.Intersected = mesh; record.T = calc.GetLineParameter(); record.Triangle = i; record.Bary[0] = calc.GetTriBary0(); record.Bary[1] = calc.GetTriBary1(); record.Bary[2] = calc.GetTriBary2(); Records.push_back(record); } } } return; } SwitchNode* switchNode = DynamicCast<SwitchNode>(object); if (switchNode) { int activeChild = switchNode->GetActiveChild(); if (activeChild != SwitchNode::SN_INVALID_CHILD) { if (switchNode->WorldBound.TestIntersection(mOrigin, mDirection, mTMin, mTMax)) { Spatial* child = switchNode->GetChild(activeChild); if (child) { ExecuteRecursive(child); } } } return; } Node* node = DynamicCast<Node>(object); if (node) { if (node->WorldBound.TestIntersection(mOrigin, mDirection, mTMin, mTMax)) { for (int i = 0; i < node->GetNumChildren(); ++i) { Spatial* child = node->GetChild(i); if (child) { ExecuteRecursive(child); } } } } }