//---------------------------------------------------------------------------- bool TriggerActor::IsPointIn(const PX2::APoint &point) const { Transform trans = WorldTransform; APoint localPoint = trans.Inverse() * point; if (mAreaType == AT_SPHERE) { Sphere3f sphere; sphere.Radius = mAreaParam[0]; if (InSphere<float>(localPoint, sphere)) return true; } else if (mAreaType == AT_BOX) { Box3f box; box.Extent[0] = mAreaParam[0]; box.Extent[1] = mAreaParam[1]; box.Extent[2] = mAreaParam[2]; if (localPoint.X() >= -box.Extent[0] && localPoint.Y() >= -box.Extent[1] && localPoint.Z() >= -box.Extent[2] && localPoint.X() <= box.Extent[0] && localPoint.Y() <= box.Extent[1] && localPoint.Z() <= box.Extent[2]) return true; } return false; }
//---------------------------------------------------------------------------- Vector2f RenderStep::PointWorldToViewPort(const APoint &point, bool *isInBack) { Rectf viewPort = mViewPort; if (viewPort.IsEmpty()) viewPort = Rectf(0.0f, 0.0f, mSize.Width, mSize.Height); HMatrix matProjView = mCamera->GetProjectionMatrix() * mCamera->GetViewMatrix(); HPoint hPoint(point.X(), point.Y(), point.Z(), point.W()); HPoint tempPoint = matProjView * hPoint; if (isInBack) { if (tempPoint.Z() <= 0) *isInBack = true; else *isInBack = false; } float wInv = 1.0f / tempPoint.W(); //投影坐标范围为[-1,1]要变成[0,1] Vector2f screenPoint; screenPoint.X() = (1.0f + tempPoint.X()*wInv) / 2.0f; screenPoint.Y() = (1.0f + tempPoint.Y()*wInv) / 2.0f; //投影坐标范围为[0,1]要变成视口内坐标 screenPoint.X() = viewPort.Left + screenPoint.X()*viewPort.Width(); screenPoint.Y() = viewPort.Bottom + screenPoint.Y()*viewPort.Height(); return screenPoint; }
//---------------------------------------------------------------------------- void ApplicationBase::OnProjectSize (int width, int height) { mUIManager->GetDefaultView()->SetSize((float)width, (float)height); APoint curPos = mUIManager->GetDefaultView()->GetCamera()->GetPosition(); mUIManager->GetDefaultView()->GetCamera()->SetPosition(APoint((float)width/2.0f, curPos.Y(), (float)height/2.0f)); }
//---------------------------------------------------------------------------- Vector2f Renderer::PointWorldToViewPort (const APoint &point, bool *isInBack) { HMatrix matProjView = GetProjectionMatrix() * GetViewMatrix(); HPoint hPoint(point.X(), point.Y(), point.Z(), point.W()); HPoint tempPoint = matProjView * hPoint; if (isInBack) { if (tempPoint.Z() <= 0) *isInBack = true; else *isInBack = false; } float wInv = 1.0f / tempPoint.W(); //投影坐标范围为[-1,1]要变成[0,1] Vector2f screenPoint; screenPoint.X() = (1.0f + tempPoint.X()*wInv)/2.0f; screenPoint.Y() = (1.0f + tempPoint.Y()*wInv)/2.0f; //投影坐标范围为[0,1]要变成视口内坐标 int viewX, viewY, viewW, viewH; GetViewport(viewX, viewY, viewW, viewH); screenPoint.X() = viewX + screenPoint.X()*viewW; screenPoint.Y() = viewY + screenPoint.Y()*viewH; return screenPoint; }
//---------------------------------------------------------------------------- bool InputPushTransformController::TransScope(APoint &pos) { if (mMinPos.X() > mMaxPos.X() || mMinPos.Y() > mMaxPos.Y() || mMinPos.Z() > mMaxPos.Z() || mMinPos == mMaxPos) { return false; } if (mMinPos.X() > pos.X()) { pos.X() = mMinPos.X(); mVelocity.X() = 0.0f; } if (mMinPos.Y() > pos.Y()) { pos.Y() = mMinPos.Y(); mVelocity.Y() = 0.0f; } if (mMinPos.Z() > pos.Z()) { pos.Z() = mMinPos.Z(); mVelocity.Z() = 0.0f; } if (pos.X() > mMaxPos.X()) { pos.X() = mMaxPos.X(); mVelocity.X() = 0.0f; } if (pos.Y() > mMaxPos.Y()) { pos.Y() = mMaxPos.Y(); mVelocity.Y() = 0.0f; } if (pos.Z() > mMaxPos.Z()) { pos.Z() = mMaxPos.Z(); mVelocity.Z() = 0.0f; } return true; }
//---------------------------------------------------------------------------- void Transform::SetScale (const APoint& scale) { if (scale.X()==scale.Y() && scale.Y()==scale.Z()) { SetUniformScale(scale.X()); } else { assertion(mIsRSMatrix, "Matrix is not a rotation\n"); assertion(scale[0] != 0.0f && scale[1] != 0.0f && scale[2] != 0.0f, "Scales must be nonzero\n"); mScale = scale; mIsIdentity = false; mIsUniformScale = false; UpdateHMatrix(); } }
//----------------------------------------------------------------------------- wxAPoint3Property::wxAPoint3Property (const wxString &label, const wxString &name, const APoint &value) : wxPGProperty(label, name) { SetValue(APointToVariant(value)); AddPrivateChild(new wxFloatProperty(wxT("X"),wxPG_LABEL,value.X())); AddPrivateChild(new wxFloatProperty(wxT("Y"),wxPG_LABEL,value.Y())); AddPrivateChild(new wxFloatProperty(wxT("Z"),wxPG_LABEL,value.Z())); }
//---------------------------------------------------------------------------- void EU_CanvasStage::_MoveCamera(float horz, float vert) { if (!Project::GetSingletonPtr()) return; Scene *scene = PX2_PROJ.GetScene(); if (!scene) return; if (mStageCameraNode) { APoint position = mStageCameraNode->LocalTransform.GetTranslate(); AVector rVector; AVector dVector; AVector uVector; mStageCameraNode->LocalTransform.GetRDUVector(rVector, dVector, uVector); if (mViewType == VT_PERSPECTIVE) { dVector.Z() = 0.0f; dVector.Normalize(); rVector.Z() = 0.0f; rVector.Normalize(); position += dVector * vert; position -= rVector * horz; } else if (mViewType == VT_TOP) { position.Y() += vert * 1.0f; position.X() -= horz * 1.0f; } else if (mViewType == VT_LEFT) { position.Z() += vert * 1.0f; position.Y() += horz * 1.0f; } else if (mViewType == VT_FRONT) { position.Z() += vert * 1.0f; position.X() -= horz * 1.0f; } mStageCameraNode->LocalTransform.SetTranslate(position); } }
//---------------------------------------------------------------------------- void Actor::SetRotation (APoint &rolate) { mRotation = rolate; if (mMovable) { mMovable->LocalTransform.SetRotate(Matrix3f().MakeEulerXYZ( rolate.X(), rolate.Y(), rolate.Z())); } }
//---------------------------------------------------------------------------- void Actor::SetRotation (const APoint &rolate) { if (rolate == mRotation) return; mRotation = rolate; if (mMovable) { mMovable->LocalTransform.SetRotate(Matrix3f().MakeEulerXYZ( rolate.X(), rolate.Y(), rolate.Z())); } if (mHelpMovable) { mHelpMovable->LocalTransform.SetRotate(Matrix3f().MakeEulerXYZ( rolate.X(), rolate.Y(), rolate.Z())); } }
//---------------------------------------------------------------------------- void EditRenderView_Scene::_MoveCamera(float horz, float vert) { Scene *scene = PX2_PROJ.GetScene(); if (!scene) return; CameraActor *camActor = scene->GetUseCameraActor(); if (camActor) { APoint position = camActor->LocalTransform.GetTranslate(); AVector rVector; AVector dVector; AVector uVector; camActor->GetRDUVector(rVector, dVector, uVector); if (mViewType == VT_PERSPECTIVE) { dVector.Z() = 0.0f; dVector.Normalize(); rVector.Z() = 0.0f; rVector.Normalize(); position += dVector * vert; position -= rVector * horz; } else if (mViewType == VT_TOP) { position.Y() += vert * 1.0f; position.X() -= horz * 1.0f; } else if (mViewType == VT_LEFT) { position.Z() += vert * 1.0f; position.Y() += horz * 1.0f; } else if (mViewType == VT_FRONT) { position.Z() += vert * 1.0f; position.X() -= horz * 1.0f; } camActor->LocalTransform.SetTranslate(position); } }
//---------------------------------------------------------------------------- void FMODSound::SetPosition (const APoint &position) { FMOD_VECTOR pos; pos.x = position.X(); pos.y = position.Y(); pos.z = position.Z(); if (mChannel) mChannel->set3DAttributes(&pos, 0); }
//----------------------------------------------------------------------------- void MovableTransProperty::OnChange (wxPropertyGridEvent &event) { if (!mProperty) return; wxPGProperty *id = event.GetProperty(); const wxString &name = event.GetPropertyName(); std::string stdName = std::string(name); wxVariant variant = id->GetValue(); if (0 == id) return; if (variant.IsNull()) return; APoint value; if (mPropertyTranslate == id) { value = APointRefFromVariant(variant); mTrans->SetTranslate(value); } else if (mPropertyRotation == id) { value = APointRefFromVariant(variant); mTrans->SetRotate(Matrix3f().MakeEulerXYZ( value.X(), value.Y(), value.Z())); } else if (mPropertyScale == id) { value = APointRefFromVariant(variant); if (value.X()!=0.0f && value.Y()!=0.0f && value.Z()!=0.0f) { mTrans->SetScale(value); } } Event *ent = 0; ent = EditEventSpace::CreateEventX(EditEventSpace::ObjectTransformChanged); ent->SetData<Object*>(mObject); EventWorld::GetSingleton().BroadcastingLocalEvent(ent); }
//---------------------------------------------------------------------------- AVector InputPushTransformController::GetSmallTransDir() { Movable *movable = DynamicCast<Movable>(mObject); if (!movable) AVector::ZERO; APoint curPos = movable->LocalTransform.GetTranslate(); AVector moveDir = AVector::ZERO; if (curPos.X() < mMinPosSmall.X()) { moveDir.X() = mMinPosSmall.X() - curPos.X(); } if (curPos.Y() < mMinPosSmall.Y()) { moveDir.Y() = mMinPosSmall.Y() - curPos.Y(); } if (curPos.Z() < mMinPosSmall.Z()) { moveDir.Z() = mMinPosSmall.Z() - curPos.Z(); } if (curPos.X()>mMaxPosSmall.X()) { moveDir.X() = mMaxPosSmall.X() - curPos.X(); } if (curPos.Y() > mMaxPosSmall.Y()) { moveDir.Y() = mMaxPosSmall.Y() - curPos.Y(); } if (curPos.Z() > mMaxPosSmall.Z()) { moveDir.Z() = mMaxPosSmall.Z() - curPos.Z(); } return moveDir; }
MovableTransProperty::MovableTransProperty (PropertyPage *parent, const std::string &name, const std::string &tag, Transform *trans, Object *obj) : Property(parent, name, tag, Property::PT_TRANSFORM, 0), mIsRSMatrix(0), mPropertyTranslate(0), mPropertyRotation(0), mPropertyScale(0), mPropertyIsUniformScale(0), mTrans(trans), mObject(obj) { APoint position; APoint rotation; APoint scale(1.0f, 1.0f, 1.0f); bool isRSMatrix = mTrans->IsRSMatrix(); if (isRSMatrix) { position = mTrans->GetTranslate(); Matrix3f mat = mTrans->GetRotate(); mat.ExtractEulerXYZ(rotation.X(), rotation.Y(), rotation.Z()); scale = mTrans->GetScale(); bool isUniformScale = mTrans->IsUniformScale(); mProperty = parent->mPage->Append(new wxStringProperty( name, tag, wxT("<composed>")) ); mPropertyTranslate = parent->mPage->AppendIn(mProperty, new wxAPoint3Property("Translate", tag+"Translate", position)); mPropertyRotation = parent->mPage->AppendIn(mProperty, new wxAPoint3Property("Rotate", tag+"Rotate", rotation)); mPropertyScale = parent->mPage->AppendIn(mProperty, new wxAPoint3Property("Scale", tag+"Scale", scale)); mPropertyIsUniformScale = parent->mPage->AppendIn(mProperty, new wxBoolProperty("IsUniformScale", tag+"IsUniformScale", isUniformScale)); mPropertyIsUniformScale->Enable(false); } else { mProperty = parent->mPage->Append(new wxStringProperty( name, tag, wxT("<composed>")) ); mIsRSMatrix = parent->mPage->AppendIn(mProperty, new wxBoolProperty("IsRSMatrix", tag+"IsRSMatrix", false)); mIsRSMatrix->Enable(false); } }
//---------------------------------------------------------------------------- void Terrain::AddJunglers (Texture2D *tex, APoint center, float radius, int num, float width, float height, float lower) { if (!tex) return; for (int i=0; i<mNumRows; i++) { for (int j=0; j<mNumCols; j++) { GetPage(i, j)->mAddingJObjs.clear(); } } for (int i=0; i<num; i++) { float unitRadius = Mathf::UnitRandom(); float fX0 = Mathf::SymmetricRandom(); float fY0 = Mathf::SymmetricRandom(); AVector normal0(fX0, fY0, 0.0f); normal0.Normalize(); float fX1 = Mathf::SymmetricRandom(); float fY1 = Mathf::SymmetricRandom(); AVector normal1(fX1, fY1, 0.0f); normal1.Normalize(); APoint pos = center + normal0*unitRadius*radius; pos.Z() = GetHeight(pos.X(), pos.Y()) - lower; JObj obj; obj.Pos = pos; obj.Normal = normal1; obj.Width = width; obj.Height = height; TerrainPage *page = GetCurrentPage(obj.Pos.X(), obj.Pos.Y()); page->mAddingJObjs.push_back(obj); } for (int i=0; i<mNumRows; i++) { for (int j=0; j<mNumCols; j++) { TerrainPage *page = GetPage(i, j); page->AddJunglers(tex, page->mAddingJObjs); } } }
//----------------------------------------------------------------------------- int CellSpace::PositionToIndex(const APoint &pos) const { float posA = pos.X(); float posB = pos.Y(); int index = (int)(posA / mCellLength) + ((int)(posB / mCellWidth) * mNumCellsLength); if (index > (int)mCells.size() - 1) index = (int)mCells.size() - 1; if (index < 0) index = 0; return index; }
//---------------------------------------------------------------------------- void Selection::AddRolate(AVector vec) { for (int i = 0; i < (int)mObjects.size(); i++) { Movable *mov = DynamicCast<Movable>(mObjects[i]); if (mov) { APoint rotation; Matrix3f mat = mov->LocalTransform.GetRotate(); mat.ExtractEulerZYX(rotation.Z(), rotation.Y(), rotation.X()); rotation += vec; Matrix3f matTrans; matTrans.MakeEulerZYX(rotation[2], rotation[1], rotation[0]); mov->LocalTransform.SetRotate(matTrans); mov->Update(Time::GetTimeInSeconds(), false); } } _UpdateSelect(); }
//---------------------------------------------------------------------------- void CurveCtrl::SetCtrlsScale (float xScale, float zScale) { mXScale = xScale; mZScale = zScale; if (mDragBox) { APoint scale = mDragBox->LocalTransform.GetScale(); mDragBox->LocalTransform.SetScale(Float3(xScale, scale.Y(), zScale)); } if (mDragBoxArrive) { mDragBoxArrive->LocalTransform.SetScale(Float3(xScale, 1.0f, zScale)); } if (mDragBoxLeave) { mDragBoxLeave->LocalTransform.SetScale(Float3(xScale, 1.0f, zScale)); } OnCtrlChanged(false); }
//---------------------------------------------------------------------------- void RawTerrain::OnCameraMotion () { assertion(mCamera != 0, "Camera must exist\n"); if (!mCamera) { return; } // 获得地形模型坐标系下相继的方位 APoint worldEye = mCamera->GetPosition(); AVector worldDir = mCamera->GetDVector(); APoint modelEye = WorldTransform.Inverse()*worldEye; AVector modelDir = WorldTransform.Inverse()*worldDir; // Update the model-space origins of the terrain pages. Start the // process by locating the page that contains the camera. float length = mSpacing*(float)(mSize - 1); float invLength = 1.0f/length; int newCameraCol = (int)Mathf::Floor(modelEye.X()*invLength); int newCameraRow = (int)Mathf::Floor(modelEye.Y()*invLength); if (newCameraCol != mCameraCol || newCameraRow != mCameraRow) { mCameraCol = newCameraCol; mCameraRow = newCameraRow; // Translate page origins for toroidal wraparound. int cminO = mCameraCol - mNumCols/2; int cminP = cminO % mNumCols; if (cminP < 0) { cminP += mNumCols; } int rminO = mCameraRow - mNumRows/2; int rminP = rminO % mNumRows; if (rminP < 0) { rminP += mNumRows; } int rO = rminO, rP = rminP; for (int row = 0; row < mNumRows; ++row) { int cO = cminO, cP = cminP; for (int col = 0; col < mNumCols; ++col) { RawTerrainPage* page = mPages[rP][cP]; Float2 oldOrigin = page->GetOrigin(); Float2 newOrigin(cO*length, rO*length); APoint pageTrn( newOrigin[0] - oldOrigin[0], newOrigin[1] - oldOrigin[1], page->LocalTransform.GetTranslate().Z()); page->LocalTransform.SetTranslate(pageTrn); ++cO; if (++cP == mNumCols) { cP = 0; } } ++rO; if (++rP == mNumRows) { rP = 0; } } Update(); } }
//---------------------------------------------------------------------------- bool PlanarShadows::OnKeyDown (unsigned char key, int x, int y) { if (WindowApplication3::OnKeyDown(key, x, y)) { return true; } switch (key) { case 'w': case 'W': mWireState->Enabled = !mWireState->Enabled; return true; case 'g': mUpdateTime += 0.01; mBiped->Update(mUpdateTime); return true; case 'G': mUpdateTime = 0.0; mBiped->Update(mUpdateTime); return true; } const float delta = 1.0f; APoint translate; switch (key) { case 'x': translate = mProjectorNode->LocalTransform.GetTranslate(); translate.X() -= delta; mProjectorNode->LocalTransform.SetTranslate(translate); mProjectorNode->Update(); break; case 'X': translate = mProjectorNode->LocalTransform.GetTranslate(); translate.X() += delta; mProjectorNode->LocalTransform.SetTranslate(translate); mProjectorNode->Update(); break; case 'y': translate = mProjectorNode->LocalTransform.GetTranslate(); translate.Y() -= delta; mProjectorNode->LocalTransform.SetTranslate(translate); mProjectorNode->Update(); break; case 'Y': translate = mProjectorNode->LocalTransform.GetTranslate(); translate.Y() += delta; mProjectorNode->LocalTransform.SetTranslate(translate); mProjectorNode->Update(); break; case 'z': translate = mProjectorNode->LocalTransform.GetTranslate(); translate.Z() -= delta; mProjectorNode->LocalTransform.SetTranslate(translate); mProjectorNode->Update(); break; case 'Z': translate = mProjectorNode->LocalTransform.GetTranslate(); translate.Z() += delta; mProjectorNode->LocalTransform.SetTranslate(translate); mProjectorNode->Update(); break; case 's': case 'S': // TODO: Test streaming. return true; default: return false; } return true; }
//---------------------------------------------------------------------------- void EditRenderView_TimeLine::OnMotion(const APoint &pos) { AVector diff = pos - mLastMousePoint; if (AVector::ZERO == diff) return; float movedX = -diff.X() / mPixelOverCamIn; float movedZ = -diff.Z() / mPixelOverCamOut; Rectf rect(0, 0, mLeftWidth, mSize.Height); bool leftContain = rect.IsInsize(Float2(pos.X(), pos.Z())); bool isCtrlDown = PX2_EDIT.IsCtrlDown; CurveCtrl *selectedCtrl = PX2_EDIT.GetTimeLineEdit()->GetSelectedCurveCtrl(); if (isCtrlDown && !leftContain && selectedCtrl && mIsLeftDown) { Camera *camera = mRenderStep->GetCamera(); const APoint &outVal = selectedCtrl->GetOutVal(); Vector2f posInViewPort = mUIViewGrid->PointWorldToViewPort(outVal); float xDiss = pos.X() - posInViewPort.X(); float zDiss = pos.Z() - posInViewPort.Y(); float xDissReal = xDiss / mPixelOverCamIn; float zDissReal = zDiss / mPixelOverCamOut; AVector arrive = AVector(-xDissReal, 0.0f, -zDissReal); arrive.Normalize(); AVector leave = AVector(xDissReal, 0.0f, zDissReal); leave.Normalize(); if (CurveCtrl::SM_ARRIVE == selectedCtrl->GetSelectMode()) { if (xDiss < 0.0f) { selectedCtrl->SetArriveTangent(arrive); InterpCurveMode mode = selectedCtrl->GetInterpCurveMode(); if (ICM_CURVE_AUTO == mode || ICM_CURVE_AUTOCLAMPED == mode) { selectedCtrl->SetInterpCurveMode(ICM_CURVE_USER); //UnToggleAllInterps(); //ToggleInterp(ICM_CURVE_USER); } } } else if (CurveCtrl::SM_LEAVE == selectedCtrl->GetSelectMode()) { if (xDiss > 0.0f) { selectedCtrl->SetLeaveTangent(leave); InterpCurveMode mode = selectedCtrl->GetInterpCurveMode(); if (ICM_CURVE_AUTO == mode || ICM_CURVE_AUTOCLAMPED == mode) { selectedCtrl->SetInterpCurveMode(ICM_CURVE_USER); //UnToggleAllInterps(); //ToggleInterp(ICM_CURVE_USER); } } } else if (CurveCtrl::SM_CENTER == selectedCtrl->GetSelectMode()) { APoint camPos = camera->GetPosition(); Vector2f camScreenPos = mUIViewGrid->PointWorldToViewPort(camPos); float xDissCam = pos.X() - camScreenPos.X(); float zDissCam = pos.Z() - camScreenPos.Y(); float xDissCamReal = xDissCam / mPixelOverCamIn; float zDissCamReal = zDissCam / mPixelOverCamOut; APoint pointPos = camPos + AVector(xDissCamReal, 0.0f, zDissCamReal); pointPos.Y() = 0.0f; selectedCtrl->SetInVal(pointPos.X()); // ctrl may changed selectedCtrl = PX2_EDIT.GetTimeLineEdit()->GetSelectedCurveCtrl(); // ctrl may changed, can it again if (selectedCtrl) selectedCtrl->SetOutVal(pointPos); } } bool doMovCal = false; if (mIsMiddleDown && !leftContain) doMovCal = true; if (mIsRightDown && !leftContain) doMovCal = true; if (doMovCal) { if (MM_PAN == mMoveMode) { APoint pos = mUIViewGrid->GetCameraNode()->LocalTransform.GetTranslate(); pos += AVector(movedX, 0.0f, movedZ); mUIViewGrid->GetCameraNode()->LocalTransform.SetTranslate(pos); mUIViewGrid->GetCameraNode()->Update(GetTimeInSeconds(), 0.0f); _RefreshGrid(false); } else if (MM_ZOOM == mMoveMode) { } } mLastMousePoint = pos; }
//---------------------------------------------------------------------------- void SceneBuilder::ProcessSkin(INode *node, Modifier *skinMod) { // 构造皮肤控制器。如果Max的网格被按照材质细分,每一个网格都需要自己的蒙皮 // 信息控制器。蒙皮信息中的offset,在动画起始时被计算,是骨骼的世界变换。 // // node: // 指向蒙皮修改器指向的Max中的节点。 // skinMod: // 指向蒙皮修改器 // 1. 获得max蒙皮信息中的骨骼,对应的在Phoenix的骨骼节点列表 // 2. 获得maxNode影响的Phoenix网格 // 3. 获得max中每个骨骼所影响的Phoenix网格中的顶点的数量,忽略不受蒙皮信息 // 影响的网格 // 4. 计算Phoenix mesh的蒙皮信息,生成SkinControl,AttachController到 // Phoenix mesh上。 // 1 bool needDel; TriObject *triObj = GetTriObject(node, &needDel); Mesh *maxMesh = &triObj->GetMesh(); // Max皮肤控制器接口 ISkin *skin = (ISkin*)skinMod->GetInterface(I_SKIN); ISkinContextData *skinData = skin->GetContextInterface(node); // max Skin Bones -> Phoenix2 Skin Bones int b, numSkinBone = skin->GetNumBones(); PX2::Node **bones = new1<PX2::Node*>(numSkinBone); for (b=0; b<numSkinBone; b++) { INode *boneNode = skin->GetBone(b); const std::string &boneName = boneNode->GetName(); PX2::Node *node = PX2::StaticCast<PX2::Node>(mScene->GetObjectByName(boneName)); bones[b] = node; } // 1 // 获得maxNode相关联的Phoenix mesh std::vector<PX2::TriMesh*> meshes; PX2::Object *object = mScene->GetObjectByName(node->GetName()); if (object->IsExactly(PX2::TriMesh::TYPE)) { meshes.push_back(PX2::StaticCast<PX2::TriMesh>(object)); } else { PX2::Node *node = PX2::StaticCast<PX2::Node>(object); const char *nName = node->GetName().c_str(); for (int c=0; c<node->GetNumChildren(); c++) { PX2::Movable *child = node->GetChild(c); const char *cName = child->GetName().c_str(); if (strncmp(cName, nName, strlen(nName)) == 0) // 这里必须是strlen(nName),因为子节点有_1,_2 { meshes.push_back(PX2::StaticCast<PX2::TriMesh>(child)); } } } // 为Phoenix2的每个网格建立相关的皮肤控制器 int *boneInfuseNumVert = new1<int>(numSkinBone); for (int m=0; m<(int)meshes.size(); m++) { PX2::TriMesh *mesh = meshes[m]; // Phoenix顶点在max顶点中的索引 PX2::VertexBuffer *vb = mesh->GetVertexBuffer(); int px2MeshVertexNum = vb->GetNumElements(); std::vector<int> MaxVertexIndex; // i->max索引 int v, i, j, k; PX2::VertexBufferAccessor vba(mesh->GetVertexFormat(), vb); // 3 for (int v=0; v<px2MeshVertexNum; ++v) { Float3 &position = vba.Position<Float3>(v); for (i=0; i<maxMesh->getNumVerts(); i++) { if (position[0] == maxMesh->verts[i].x && position[1] == maxMesh->verts[i].y && position[2] == maxMesh->verts[i].z) { MaxVertexIndex.push_back(i); break; } } } // 确定每个骨骼所影响的顶点数量 int maxVertexSize = (int)MaxVertexIndex.size(); memset(boneInfuseNumVert, 0, sizeof(int)*numSkinBone); for (i=0; i<maxVertexSize; i++) { v = MaxVertexIndex[i]; for (j=0; j<skinData->GetNumAssignedBones(v); j++) { // 这个max中的顶点受到几个骨骼影响啊?! b = skinData->GetAssignedBone(v, j); // 获得这个影响的骨骼索引(这个j是第几个) boneInfuseNumVert[b]++; // 这个骨骼影响的顶点数量++ } } // (通过PX2中的顶点找到Max中的顶点,找到Max中影响该顶点的骨骼) // 如果Max的网格是被按照材质分割的,可能一些骨骼对当前Phoenix2网格没有 // 影响 int bQuantity = 0; // 影响当前Phoenix2网格的骨骼数量 for (b=0; b<numSkinBone; b++) { if (boneInfuseNumVert[b] > 0) bQuantity++; } if (bQuantity == 0) { // Phoenix网格不被任何骨骼影响,进入下一个网格 continue; } // 4 PX2::Node **theBones = new1<PX2::Node*>(bQuantity); float **weight = new2<float>(bQuantity, maxVertexSize); memset(weight[0],0,bQuantity*maxVertexSize*sizeof(float)); PX2::APoint **offset = new2<PX2::APoint>(bQuantity, maxVertexSize); memset(offset[0],0,bQuantity*maxVertexSize*sizeof(PX2::APoint)); PX2::HMatrix *mats = new1<PX2::HMatrix>(bQuantity); // 计算max骨骼到Phoenix骨骼对应的索引(k) std::vector<int> bIArray(numSkinBone); for (b=0, k=0; b<numSkinBone; b++) { if (boneInfuseNumVert[b] > 0) { theBones[k] = bones[b]; // 获取对Mesh有影响的骨骼 bIArray[b] = k; // max bone index -> px2 可用bone index HMatrix boneWorldMat = theBones[k]->WorldTransform.Matrix(); HMatrix meshWorldMat = mesh->WorldTransform.Matrix(); mats[k] = boneWorldMat.Inverse() * meshWorldMat; k++; } } // 遍历顶点,计算顶点权重和offset for (i=0; i<maxVertexSize; i++) { v = MaxVertexIndex[i]; for (j=0; j<skinData->GetNumAssignedBones(v); j++) { // 遍历影响该Max顶点的骨骼 b = skinData->GetAssignedBone(v, j); k = bIArray[b]; float wit = skinData->GetBoneWeight(v, j); // 第j个骨骼的影响权重 weight[i][k] = wit; Float3 &position = vba.Position<Float3>(i); APoint point = theBones[k]->WorldTransform.Inverse() * (mesh->WorldTransform * APoint(position)); offset[i][k] = Float3(point.X(), point.Y(), point.Z()); // 在所受影响骨骼中的位置 } } PX2::SkinController *skinCtrl = new0 PX2::SkinController (maxVertexSize, bQuantity); skinCtrl->SetName("SkinController"); for (int i=0; i<bQuantity; i++) { skinCtrl->GetBones()[i] = theBones[i]; skinCtrl->GetTMMatrixs()[i] = mats[i]; } // offset for (int i=0; i<maxVertexSize; i++) { for (int j=0; j<bQuantity; j++) { skinCtrl->GetWeights()[i][j] = weight[i][j]; skinCtrl->GetOffsets()[i][j] = offset[i][j]; } } // index weights for (int i=0; i<maxVertexSize; i++) { Float4 inds = Float4(0.0f, 0.0f, 0.0f, 0.0f); Float4 wights = Float4(0.0f, 0.0f, 0.0f, 0.0f); In *pSortBone = new In[bQuantity]; for (int j=0; j<bQuantity; j++) { pSortBone[j].index = j; pSortBone[j].data = weight[i][j]; } qsort(pSortBone, bQuantity, sizeof(pSortBone[0]), cmp); int useBoneNum = bQuantity; if (useBoneNum > 4) useBoneNum = 4; float allWeight = 0.0f; for (int useBoneIndex=0; useBoneIndex<useBoneNum; useBoneIndex++) { allWeight += pSortBone[useBoneIndex].data; } if (allWeight <= 0.0f) allWeight = 1.0f; for (int useBoneIndex=0; useBoneIndex<useBoneNum; useBoneIndex++) { inds[useBoneIndex] = (float)(pSortBone[useBoneIndex].index); wights[useBoneIndex] = pSortBone[useBoneIndex].data/allWeight; } vba.TCoord<Float4>(1, i) = inds; vba.TCoord<Float4>(2, i) = wights; delete [] pSortBone; } skinCtrl->Repeat = Controller::RT_WRAP; skinCtrl->MinTime = 0.0f; skinCtrl->MaxTime = TicksToSec(mTimeEnd - mTimeStart); mesh->AttachController(skinCtrl); delete1(theBones); delete2(weight); delete2(offset); delete1(mats); } if (needDel) { delete0(triObj); } delete1(bones); delete1(boneInfuseNumVert); }
//---------------------------------------------------------------------------- void SizeNode::UpdateLayout(Movable *parent) { Movable *par = parent; if (!par) return; SizeNode *parNode = DynamicCast<SizeNode>(par); // parent pvoit决定了从那一点作为原点,计算当前Frame原点位置 // 例如 // (0.0f, 0.0f)是左下角 // (0.5f, 0.5f)是中心点 Sizef parentSize; AVector parentLeftBottomOffset; if (parNode) { parentSize = parNode->GetSize(); parentLeftBottomOffset = parNode->LeftBottomCornerOffset; } APoint localPos = LocalTransform.GetTranslate(); Sizef localSize = GetSize(); APoint newPos; Sizef newSize = localSize; if (parNode) { float width = 0.0f; float height = 0.0f; bool isHEqual = (mAnchorHor[0] == mAnchorHor[1]); bool isVEqual = (mAnchorVer[0] == mAnchorVer[1]); if (isHEqual) { width = localSize.Width; newPos.X() = parentLeftBottomOffset.X() + parentSize.Width * mAnchorHor[0] + mAnchorParamHor[0]; } else { // 如果是范围,直接取中心点,作为原点 width = parentSize.Width * (mAnchorHor[1] - mAnchorHor[0]) - mAnchorParamHor[0] + mAnchorParamHor[1]; newPos.X() = parentLeftBottomOffset.X() + parentSize.Width*mAnchorHor[0] + mAnchorParamHor[0] + width / 2.0f; } if (isVEqual) { height = localSize.Height; newPos.Z() = parentLeftBottomOffset.Z() + parentSize.Height * mAnchorVer[0] + mAnchorParamVer[0]; } else { // 如果是范围,直接取中心点,作为原点 height = parentSize.Height * (mAnchorVer[1] - mAnchorVer[0]) - mAnchorParamVer[0] + mAnchorParamVer[1]; newPos.Z() = parentLeftBottomOffset.Z() + parentSize.Height*mAnchorVer[0] + mAnchorParamVer[0] + height / 2.0f; } newSize = Sizef(width, height); } newPos.Y() = localPos.Y(); LocalTransform.SetTranslate(newPos); if (newSize != localSize) { SetSize(newSize); } }
//---------------------------------------------------------------------------- bool PolyhedronDistance::ApplyTransform (unsigned char key) { APoint trn; HMatrix rot, incr; float trnSpeed = 0.1f; float rotSpeed = 0.1f; switch (key) { case 'x': trn = mTetras[0]->LocalTransform.GetTranslate(); trn.X() -= trnSpeed; mTetras[0]->LocalTransform.SetTranslate(trn); break; case 'X': trn = mTetras[0]->LocalTransform.GetTranslate(); trn.X() += trnSpeed; mTetras[0]->LocalTransform.SetTranslate(trn); break; case 'y': trn = mTetras[0]->LocalTransform.GetTranslate(); trn.Y() -= trnSpeed; mTetras[0]->LocalTransform.SetTranslate(trn); break; case 'Y': trn = mTetras[0]->LocalTransform.GetTranslate(); trn.Y() += trnSpeed; mTetras[0]->LocalTransform.SetTranslate(trn); break; case 'z': trn = mTetras[0]->LocalTransform.GetTranslate(); trn.Z() -= trnSpeed; mTetras[0]->LocalTransform.SetTranslate(trn); break; case 'Z': trn = mTetras[0]->LocalTransform.GetTranslate(); trn.Z() += trnSpeed; mTetras[0]->LocalTransform.SetTranslate(trn); break; case 's': trn = mTetras[1]->LocalTransform.GetTranslate(); trn.X() -= trnSpeed; mTetras[1]->LocalTransform.SetTranslate(trn); break; case 'S': trn = mTetras[1]->LocalTransform.GetTranslate(); trn.X() += trnSpeed; mTetras[1]->LocalTransform.SetTranslate(trn); break; case 't': trn = mTetras[1]->LocalTransform.GetTranslate(); trn.Y() -= trnSpeed; mTetras[1]->LocalTransform.SetTranslate(trn); break; case 'T': trn = mTetras[1]->LocalTransform.GetTranslate(); trn.Y() += trnSpeed; mTetras[1]->LocalTransform.SetTranslate(trn); break; case 'u': trn = mTetras[1]->LocalTransform.GetTranslate(); trn.Z() -= trnSpeed; mTetras[1]->LocalTransform.SetTranslate(trn); break; case 'U': trn = mTetras[1]->LocalTransform.GetTranslate(); trn.Z() += trnSpeed; mTetras[1]->LocalTransform.SetTranslate(trn); break; case 'a': rot = mTetras[0]->LocalTransform.GetRotate(); incr.MakeRotation(AVector::UNIT_Y, rotSpeed); mTetras[0]->LocalTransform.SetRotate(incr*rot); break; case 'A': rot = mTetras[0]->LocalTransform.GetRotate(); incr.MakeRotation(AVector::UNIT_Y, -rotSpeed); mTetras[0]->LocalTransform.SetRotate(incr*rot); break; case 'b': rot = mTetras[1]->LocalTransform.GetRotate(); incr.MakeRotation(AVector::UNIT_Z, rotSpeed); mTetras[1]->LocalTransform.SetRotate(incr*rot); break; case 'B': rot = mTetras[1]->LocalTransform.GetRotate(); incr.MakeRotation(AVector::UNIT_Z, -rotSpeed); mTetras[1]->LocalTransform.SetRotate(incr*rot); break; case 'c': rot = mTetras[0]->LocalTransform.GetRotate(); incr.MakeRotation(AVector::UNIT_X, 1.3f*rotSpeed); mTetras[0]->LocalTransform.SetRotate(incr*rot); rot = mTetras[1]->LocalTransform.GetRotate(); incr.MakeRotation(AVector::UNIT_Z, -rotSpeed); mTetras[1]->LocalTransform.SetRotate(incr*rot); break; case 'C': rot = mTetras[0]->LocalTransform.GetRotate(); incr.MakeRotation(AVector::UNIT_X, -1.3f*rotSpeed); mTetras[0]->LocalTransform.SetRotate(incr*rot); rot = mTetras[1]->LocalTransform.GetRotate(); incr.MakeRotation(AVector::UNIT_Z, rotSpeed); mTetras[1]->LocalTransform.SetRotate(incr*rot); break; default: return false; } // Prevent solution point coordinates from being negative. The polyhedron // distance calculator expects solution points to be in the first octant. // Vertices are offset by mOffsetMagnitude*Vector3f(1,1,1) in // UpdateSegments() before the call to the distance routine. Here we make // sure that no translation of a polyhedron takes it so far into one of the // other 7 octants that the offset will not be sufficient to guarantee that // the solution points lie in the first octant. VertexBufferAccessor vba; float threshold = -mOffsetMagnitude + trnSpeed; for (int j = 0; j < 2; ++j) { const APoint& wTrn = mTetras[j]->WorldTransform.GetTranslate(); const HMatrix& wRot = mTetras[j]->WorldTransform.GetRotate(); vba.ApplyTo(mTetras[j]); for (int i = 0; i < 4; i++) { AVector relPosition = vba.Position<Float3>(i); APoint position = wTrn + wRot*relPosition; APoint trn = mTetras[j]->LocalTransform.GetTranslate(); for (int k = 0; k < 3; ++k) { if (position[k] < threshold) { trn[k] += trnSpeed; } } mTetras[j]->LocalTransform.SetTranslate(trn); } } mScene->Update(); UpdateSegments(); return true; }