void NifImporter::ImportBones(NiNodeRef node, bool recurse)
{
   try 
   {
      if (uncontrolledDummies)
         BuildControllerRefList(node, ctrlCount);

      string name = node->GetName();

      vector<NiAVObjectRef> children = node->GetChildren();
      vector<NiNodeRef> childNodes = DynamicCast<NiNode>(children);

      NiAVObject::CollisionType cType = node->GetCollisionMode();
      if (children.empty() && name == "Bounding Box")
         return;

      // Do all node manipulations here
      NiNodeRef parent = node->GetParent();
      string parentname = (parent ? parent->GetName() : "");
      Matrix44 m4 = node->GetWorldTransform();

      // Check for Prn strings and change parent if necessary
      if (supportPrnStrings) {
         list<NiStringExtraDataRef> strings = DynamicCast<NiStringExtraData>(node->GetExtraData());
         for (list<NiStringExtraDataRef>::iterator itr = strings.begin(); itr != strings.end(); ++itr){
            if (strmatch((*itr)->GetName(), "Prn")) {
               parentname = (*itr)->GetData();
               if (INode *pn = gi->GetINodeByName(parentname.c_str())){
                  // Apparently Heads tend to need to be rotated 90 degrees on import for 
                  if (!rotate90Degrees.empty() && wildmatch(rotate90Degrees, parentname)) {
                     m4 *= TOMATRIX4(RotateYMatrix(TORAD(90)));
                  }
                  m4 *= TOMATRIX4(pn->GetObjTMAfterWSM(0, NULL));
               }
            }
         }
      }

      float len = node->GetLocalTranslation().Magnitude();

      // Remove NonAccum nodes and merge into primary bone
      if (mergeNonAccum && wildmatch("* NonAccum", name) && parent)
      {
         string realname = name.substr(0, name.length() - 9);
         if (strmatch(realname, parent->GetName()))
         {
            Matrix44 tm = parent->GetLocalTransform() * node->GetLocalTransform();
            name = realname;
            len += tm.GetTranslation().Magnitude();
			parent = parent->GetParent();
         }
      }

      PosRotScale prs = prsDefault;
      Vector3 pos; Matrix33 rot; float scale;
      m4.Decompose(pos, rot, scale);

      Matrix3 im = TOMATRIX3(m4);
      Point3 p = im.GetTrans();
      Quat q(im);
      //q.Normalize();
      Vector3 ppos;
      Point3 zAxis(0,0,0);
      bool hasChildren = !children.empty();
      if (hasChildren) {
         float len = 0.0f;
         for (vector<NiAVObjectRef>::iterator itr=children.begin(), end = children.end(); itr != end; ++itr) {
            len += GetObjectLength(*itr);
         }
         len /= float(children.size());
         ppos = pos + Vector3(len, 0.0f, 0.0f); // just really need magnitude as rotation will take care of positioning
      }
      else if (parent)
      {
         ppos = pos + Vector3(len/3.0f, 0.0f, 0.0f);
      }
      Point3 pp(ppos.x, ppos.y, ppos.z);

      Point3 qp = TORAD(TOEULER(im));


      INode *bone = NULL;
	  if (!doNotReuseExistingBones) // Games like BC3 reuse the same bone names
	  {
		  bone = FindNode(node);
		  if (bone == NULL) 
			  bone = gi->GetINodeByName(name.c_str());
	  }
      if (bone)
      {
         // Is there a better way of "Affect Pivot Only" behaviors?
         INode *pinode = bone->GetParentNode();
         if (pinode)
            bone->Detach(0,1);
         PosRotScaleNode(bone, p, q, scale, prs);
         if (pinode)
            pinode->AttachChild(bone, 1);
      }
      else
      {
         bool isDummy = ( (uncontrolledDummies && !HasControllerRef(ctrlCount, name))
                     || (!dummyNodeMatches.empty() && wildmatch(dummyNodeMatches, name))
                     || (convertBillboardsToDummyNodes && node->IsDerivedType(NiBillboardNode::TYPE))
                      );
         if (wildmatch("Camera*", name)) {
            if (enableCameras) {
               if (bone = CreateCamera(name)) {
                  PosRotScaleNode(bone, p, q, scale, prs);
                  bone->Hide(node->GetVisibility() ? FALSE : TRUE);
               }
            }
         }else if (isDummy && createNubsForBones)
            bone = CreateHelper(name, p);
         else if (bone = CreateBone(name, p, pp, zAxis))
         {
            PosRotScaleNode(bone, p, q, scale, prs);
            bone->Hide(node->GetVisibility() ? FALSE : TRUE);
         }
         if (bone)
         {
            if (!parentname.empty())
            {
               if (mergeNonAccum && wildmatch("* NonAccum", parentname)) {
                  parentname = parentname.substr(0, parentname.length() - 9);
               }
               if (INode *pn = gi->GetINodeByName(parentname.c_str()))
                  pn->AttachChild(bone, 1);
            }
			RegisterNode(node, bone);
         }
      }
      // Import UPB
      if (bone) ImportUPB(bone, node);

      // Import Havok Collision Data surrounding node,  
	  //   unfortunately this causes double import of collision so I'm disabling it for now.
	  if (enableCollision && node->GetParent()) {
		ImportCollision(node);
	  }

      if (bone && recurse)
      {
         ImportBones(childNodes);
      }
   }
   catch( exception & e ) 
   {
      e=e;
   }
   catch( ... ) 
   {
   }
}
Beispiel #2
0
	void Frustum::Update(const Matrix44<float>& aCameraOrientation, float aAspectRatio, float aFov)
	{
		float Hnear = 2.f * tan(aFov / 2.f) * myNear;
		float Wnear = Hnear * aAspectRatio;

		myPosition = aCameraOrientation.GetTranslation();
		Vector3f rightVector = GetNormalized(aCameraOrientation.GetRightVector());
		Vector3f forwardVector = GetNormalized(aCameraOrientation.GetForwardVector());
		Vector3f upVector = GetNormalized(aCameraOrientation.GetUpVector());
		
		Vector3f nc = myPosition + forwardVector * myNear;

		Vector3f ntl = nc + (upVector * Hnear / 2.f) - (rightVector * Wnear / 2.f);
		Vector3f ntr = nc + (upVector * Hnear / 2.f) + (rightVector * Wnear / 2.f);
		Vector3f nbl = nc - (upVector * Hnear / 2.f) - (rightVector * Wnear / 2.f);
		Vector3f nbr = nc - (upVector * Hnear / 2.f) + (rightVector * Wnear / 2.f);

		float Hfar = 2.f * tan(aFov / 2.f) * myFar;
		float Wfar = Hfar * aAspectRatio;

		Vector3f fc = myPosition + forwardVector * myFar;

		Vector3f ftl = fc + (upVector * Hfar / 2.f) - (rightVector * Wfar / 2.f);
		Vector3f ftr = fc + (upVector * Hfar / 2.f) + (rightVector * Wfar / 2.f);
		Vector3f fbl = fc - (upVector * Hfar / 2.f) - (rightVector * Wfar / 2.f);
		Vector3f fbr = fc - (upVector * Hfar / 2.f) + (rightVector * Wfar / 2.f);

		myPointPositions[0] = ntl;
		myPointPositions[1] = ntr;
		myPointPositions[2] = nbl;
		myPointPositions[3] = nbr;
		myPointPositions[4] = ftl;
		myPointPositions[5] = ftr;
		myPointPositions[6] = fbl;
		myPointPositions[7] = fbr;

		Plane<float> plane;
		plane.InitWith3Points(myPosition, nbr, ntr);
		myPlanes[int(eFRUSTUMSIDES::eRIGHT)] = plane;

		plane.InitWith3Points(myPosition, ntl, nbl);
		myPlanes[int(eFRUSTUMSIDES::eLEFT)] = plane;

		plane.InitWith3Points(myPosition, ntr, ntl);
		myPlanes[int(eFRUSTUMSIDES::eUP)] = plane;

		plane.InitWith3Points(myPosition, nbl, nbr);
		myPlanes[int(eFRUSTUMSIDES::eDOWN)] = plane;

		plane.InitWithPointAndNormal(myPosition + (forwardVector * myFar), forwardVector);
		myPlanes[int(eFRUSTUMSIDES::eFAR)] = plane;

		plane.InitWithPointAndNormal(myPosition + (forwardVector * myNear), (forwardVector * -1.f));
		myPlanes[int(eFRUSTUMSIDES::eNEAR)] = plane;

		myPosition += forwardVector * (myFar / 2.f);

		myLines.RemoveAll();

		//Near Plane

		myLines.Add(CU::RenderCommandLine(ntl, ntr));
		myLines.Add(CU::RenderCommandLine(ntr, nbr));
		myLines.Add(CU::RenderCommandLine(nbr, nbl));
		myLines.Add(CU::RenderCommandLine(nbl, ntl));

		//Far plane

		myLines.Add(CU::RenderCommandLine(ftl, ftr));
		myLines.Add(CU::RenderCommandLine(ftr, fbr));
		myLines.Add(CU::RenderCommandLine(fbr, fbl));
		myLines.Add(CU::RenderCommandLine(fbl, ftl));

		//Sides

		myLines.Add(CU::RenderCommandLine(ntl, ftl));
		myLines.Add(CU::RenderCommandLine(ntr, ftr));
		myLines.Add(CU::RenderCommandLine(nbr, fbr));
		myLines.Add(CU::RenderCommandLine(nbl, fbl));
	}