Air::U1 MeshEntity::RayCast( const Ray& ray ,float* pOutDistance) { #if 1 if(!GetWorldBoundingBox().RayCast(ray.GetOrigin(),ray.GetDirection())){//.Intersect(GetWorldBoundingBox())){ return false; } #endif Matrix matWorld = *GetWorldMatrix(); Matrix matWorldInv = matWorld; matWorldInv.Inverse(); Float3 vStart = ray.m_vStart; Float3 vLookAt = vStart + ray.m_vDirection; vStart = matWorldInv*vStart; vLookAt = matWorldInv*vLookAt; Float3 vDir = (vLookAt - vStart); vDir.Normalize(); Ray objSpaceRay(vStart,vDir); float fDistance = 999999.0f; U1 bHit = m_pMesh->RayCast(objSpaceRay,&fDistance); if(bHit && pOutDistance!=NULL){ Float3 vObjSpaceHitPostion = vStart + vDir*fDistance; Float3 vWorldSpaceHiPosition = matWorld*vObjSpaceHitPostion; *pOutDistance = (vWorldSpaceHiPosition - ray.m_vStart).Length(); } return bHit; }
Air::U1 Actor::Move(float fTimeDelta) { if(m_MoveState==enAMS_NoMove){ return false; } Float3 vMoveDir = m_vMoveDir; vMoveDir.y=0.0f; vMoveDir.Normalize(); Float3 vOldPos = m_pNode->GetPosition(); Float3 vCurrentPos = m_pNode->GetPosition(); //vCurrentPos += vMoveDir*fSensitivity; Float3 vNewVelocity = vMoveDir*m_fMoveVelocity; vNewVelocity.y = m_vMoveDir.y; PhysicsSystem::GetSingleton()->Silumation(vCurrentPos,0.5,1,vNewVelocity,fTimeDelta); m_vMoveDir.y = vNewVelocity.y; if(vCurrentPos.y<-1){ vCurrentPos.y=1; m_vMoveDir.y = 0; } m_pNode->SetPosition(vCurrentPos); return true; }
Air::Ray Frustum::BuildRay( Real x,Real y ) { #if 0 POINT point; point.x = x; point.y = y; Common::Matrix mInverseView = m_matView; mInverseView.Inverse(); // Compute the vector of the pick ray in screen space Float3 v; v.x = ( ( ( 2.0f * point.x ) / m_iScreenWidth ) - 1 ) /m_matProj.m00; v.y = -( ( ( 2.0f * point.y ) / m_iScreenHeight ) - 1 ) /m_matProj.m11; //如果是右手坐标系 Z必须为-1 左手坐标系为1 切需注意 v.z = 1;//-m_ShaderParam.m_matProj[3][2]; Ray ray; // Transform the screen space pick ray into 3D space ray.m_vDirection.x = v.x * mInverseView.m00 + v.y * mInverseView.m10 + v.z * mInverseView.m20; ray.m_vDirection.y = v.x * mInverseView.m01 + v.y * mInverseView.m11 + v.z * mInverseView.m21; ray.m_vDirection.z = v.x * mInverseView.m02 + v.y * mInverseView.m12 + v.z * mInverseView.m22; // //origin = m_vCurrentPosition; ray.m_vStart = Float3(mInverseView.m30,mInverseView.m31,mInverseView.m32); //Ray ray; ray.m_vDirection.Normalize(); return ray; #else Matrix inverseVP = m_matViewProj; inverseVP.Inverse(); Real nx = (2.0f * x) - 1.0f; Real ny = 1.0f - (2.0f * y); // Use midPoint rather than far point to avoid issues with infinite projection Float3 midPoint (nx, ny, 0.0f); // Get ray origin and ray target on near plane in world space Float3 rayTarget; rayTarget = inverseVP * midPoint; Float3 rayDirection = rayTarget - GetPosition(); rayDirection.Normalize(); return Ray(GetPosition(),rayDirection); #endif }
void MeshGroup::_genMesh(const Array<Mesh *> & arr, int first, int last, bool hasLightingColor) { MeshSourcePtr source = arr[0]->GetSource(); Mesh * mesh = new Mesh; for (int i = 0; i < source->GetMeshBufferCount(); ++i) { SubMesh * submesh = mesh->NewSubMesh(); VertexBufferPtr srcVB = source->GetMeshBuffer(i)->GetRenderOp()->vertexBuffers[0]; IndexBufferPtr srcIB = source->GetMeshBuffer(i)->GetRenderOp()->indexBuffer; int p_offset = source->GetMeshBuffer(i)->GetRenderOp()->vertexDeclarations[0].GetElementOffset(eVertexSemantic::POSITION); int n_offset = source->GetMeshBuffer(i)->GetRenderOp()->vertexDeclarations[0].GetElementOffset(eVertexSemantic::NORMAL); int stride = srcVB->GetStride(); VertexBufferPtr vb = HWBufferManager::Instance()->NewVertexBuffer(stride, srcVB->GetCount() * (last - first)); const char * v_src = (const char *)srcVB->Lock(eLockFlag::READ); char * v_dest = (char *)vb->Lock(eLockFlag::WRITE); for (int j = first; j < last; ++j) { const Mat4 & worldTM = arr[j]->GetWorldTM(); bool hasScale = arr[j]->GetWorldScale() != Float3(1, 1, 1); for (int k = 0; k < srcVB->GetCount(); ++k) { memcpy(v_dest, v_src, stride); Float3 * position = (Float3 *)(v_dest + p_offset); position->TransformA(worldTM); if (n_offset != -1) { Float3 * normal = (Float3 *)(v_dest + n_offset); normal->TransformN(worldTM); if (hasScale) { normal->Normalize(); } } v_dest += stride; v_src += stride; } } vb->Unlock(); srcVB->Unlock(); IndexBufferPtr ib = HWBufferManager::Instance()->NewIndexBuffer(srcIB->GetCount() * (last - first)); int startVertex = 0; const short * i_src = (const short *)srcIB->Lock(eLockFlag::READ); char * i_dest = (char *)ib->Lock(eLockFlag::WRITE); for (int j = first; j < last; ++j) { for (int k = 0; k < srcIB->GetCount(); ++k) { *i_dest++ = (*i_src++) + startVertex; } startVertex += srcVB->GetCount(); } ib->Unlock(); srcIB->Unlock(); submesh->GetRenderOp()->vertexDeclarations[0] = source->GetMeshBuffer(i)->GetRenderOp()->vertexDeclarations[0]; submesh->GetRenderOp()->vertexBuffers[0] = vb; submesh->GetRenderOp()->indexBuffer = ib; submesh->GetRenderOp()->primCount = ib->GetCount() / 3; submesh->GetRenderOp()->primType = ePrimType::TRIANGLE_LIST; if (hasLightingColor) { int count = submesh->GetRenderOp()->vertexBuffers[0]->GetCount(); submesh->GetRenderOp()->vertexDeclarations[LIGHTING_COLOR_STREAM].AddElement(eVertexSemantic::LIGHTING_COLOR, eVertexType::UBYTE4); submesh->GetRenderOp()->vertexBuffers[LIGHTING_COLOR_STREAM] = HWBufferManager::Instance()->NewVertexBuffer(4, count); Array<Rgba32> lightColors; Rgba32 * data = (Rgba32 *)submesh->GetRenderOp()->vertexBuffers[LIGHTING_COLOR_STREAM]->Lock(eLockFlag::WRITE); for (int j = first; j < last; ++j) { arr[j]->GetLightingColor(lightColors); d_assert (lightColors.Size() > 0); memcpy(data, &lightColors[0], 4 * count); startVertex += count; lightColors.Clear(); } submesh->GetRenderOp()->vertexBuffers[LIGHTING_COLOR_STREAM]->Unlock(); } *submesh->GetMaterial() = *source->GetMeshBuffer(i)->GetMaterial(); submesh->SetMeshShader(source->GetMeshBuffer(i)->GetShader()); } mesh->SetSLMode(hasLightingColor ? eStaticLightingMode::LIGHTING_COLOR : eStaticLightingMode::NONE); mMeshes.PushBack(mesh); }
Air::Engine::enumMouseRayCastType ObjectController::ChangeType( const Float3& vStart,const Float3& vDir ) { Float44 matWorldInv = m_WorldMatrix; matWorldInv.Inverse(); Float3 vNewStart = matWorldInv*vStart; Float3 vNewDir = matWorldInv*(vStart+vDir) - vNewStart; vNewDir.Normalize(); float fDistance = vStart.Distance(m_WorldMatrix.GetPosition())*0.1; //if(m_WorldBound.RayCast(vStart,vDir)) { switch(m_ControlMode){ case eMCM_Select:{ }break; case eMCM_Move: case eMCM_Scale:{ BoundingBox AXIS[3]; AXIS[0].vMin = Float3(0,-0.05,-0.05)*fDistance; AXIS[0].vMax = Float3(1,0.05,0.05)*fDistance; AXIS[1].vMin = Float3(-0.05,0,-0.05)*fDistance; AXIS[1].vMax = Float3(0.05,1,0.05)*fDistance; AXIS[2].vMin = Float3(-0.05,-0.05,0)*fDistance; AXIS[2].vMax = Float3(0.05,0.05,1)*fDistance; for(int i=0;i<3;i++){ if(AXIS[i].RayCast(vNewStart,vNewDir)){ m_RayCastType = enumMouseRayCastType(i+1); #if 0 char str[64]; sprintf_s(str,"%d\n",m_RayCastType); OutputDebugStringA(str); #endif break; }else{ m_RayCastType = eMRCT_None; } } }break; case eMCM_Rotate:{ BoundingBox AXIS[3]; AXIS[0].vMin = Float3(-0.01,-1,-1)*fDistance; AXIS[0].vMax = Float3(0.01,1,1)*fDistance; AXIS[1].vMin = Float3(-1,-0.01,-1)*fDistance; AXIS[1].vMax = Float3(1,0.01,1)*fDistance; AXIS[2].vMin = Float3(-1,-1,-0.01)*fDistance; AXIS[2].vMax = Float3(1,1,0.01)*fDistance; float fDis[3]={10000,10000,10000}; bool bHit = false; for(int i=0;i<3;i++){ if(AXIS[i].RayCast(vNewStart,vNewDir,&fDis[i],NULL)){ Float3 hitPos = vNewDir*fDis[i]+vNewStart; float dis = (hitPos.Distance(Float3(0,0,0)))/fDistance; if(dis < 1.0 && dis > 0.8f){ bHit = true; }else{ fDis[i] = 10000.0f; } } } if(bHit){ m_RayCastType = eMRCT_X; for(int i=1;i<3;i++){ if(fDis[i] < fDis[0]){ fDis[0] = fDis[i]; m_RayCastType = enumMouseRayCastType(i+1); } } #if 0 char str[64]; sprintf_s(str,"%d\n",m_RayCastType); OutputDebugStringA(str); #endif }else{ m_RayCastType = eMRCT_None; } }break; } } return m_RayCastType; }
void PS_Billboard::_getBillboardXYAxis(Float3 & xAxis, Float3 & yAxis, const Float3 & pos, const Float3 & dir) { int type = mParent->GetBillboardType(); bool facing = mParent->IsAccurateFacing(); switch (type) { case PS_BillboardType::POINT: if (facing) { Float3 vCamDir = pos - mCamPos; vCamDir.Normalize(); yAxis = mCamYAxis; xAxis = Float3::Cross(yAxis, vCamDir); xAxis.Normalize(); } else { xAxis = mCamXAxis; yAxis = mCamYAxis; } break; case PS_BillboardType::ORIENTED: if (facing) { Float3 vCamDir = pos - mCamPos; vCamDir.Normalize(); yAxis = dir; xAxis = Float3::Cross(yAxis, vCamDir); xAxis.Normalize(); } else { yAxis = dir; xAxis = Float3::Cross(yAxis, mCamZAxis); xAxis.Normalize(); } break; case PS_BillboardType::ORIENTED_COMMON: if (facing) { Float3 vCamDir = pos - mCamPos; vCamDir.Normalize(); yAxis = mCommonDir; xAxis = Float3::Cross(yAxis, vCamDir); xAxis.Normalize(); } else { yAxis = mCommonDir; xAxis = Float3::Cross(yAxis, mCamZAxis); xAxis.Normalize(); } break; case PS_BillboardType::PERPENDICULAR: { xAxis = Float3::Cross(mCommonUp, dir); yAxis = Float3::Cross(dir, xAxis); xAxis.Normalize(); yAxis.Normalize(); } break; case PS_BillboardType::PERPENDICULAR_COMMON: { xAxis = Float3::Cross(mCommonUp, mCommonDir); yAxis = mCommonDir; xAxis.Normalize(); } break; } }