float Float3::Distance(const Float3& a, const Float3& b) { XMVECTOR x = a.ToSIMD(); XMVECTOR y = b.ToSIMD(); XMVECTOR length = XMVector3Length(XMVectorSubtract(x, y)); return XMVectorGetX(length); }
void Blast::OnTriggerStay(EDGameCore::ICollider* thisCollider, EDGameCore::ICollider* otherCollider, const EDCollision::Contact& contact) { if( otherCollider->GetAttachedRigidBody() != 0 ) { EDCollision::Contact contact2 = contact; Float3 delta = otherCollider->GetTransform()->GetWorldMatrix().WAxis - GetTransform()->GetWorldMatrix().WAxis; if( DotProduct( delta, contact.Normal ) < 0.0f ) contact2.negate(); float mag = delta.magnitude(); if( mag == 0.0f ) { delta = Float3(0.0f, 1.0f, 0.0f); mag = 1.0f; } else delta *= (1.0f / mag); delta *= 15000.0f / (mag*mag); delta *= (1.0f / EDGameCore::Game::GetDeltaTime()); otherCollider->GetAttachedRigidBody()->ApplyForceAtPoint( delta, contact2.Point[0] ); } }
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; }
void LookAt::LateUpdate() { Transform* looker_transform = GetGameObject()->GetTransform(); Transform* target_transform = nullptr; // Finds the target based on its instance id each update // to avoid having a dangling pointer // to an object that might have been destroyed. target = GameObject::GetGameObjectInstance(targetId); // TODO - comment this out and write your own solution target_transform = target->GetTransform(); Float4x4 lookerMatrix = looker_transform->GetLocalMatrix(); Float4x4 targetMatrix = target_transform->GetLocalMatrix(); Float3 lookerPos = Float3(lookerMatrix.WAxis); Float3 targetPos = Float3(targetMatrix.WAxis); Float3 xAxis = ZERO_VECTOR; Float3 yAxis = ZERO_VECTOR; Float3 zAxis = (targetPos - lookerPos).normalize(); CrossProduct(xAxis, zAxis, Float3(0.0f, 1.0f, 0.0f)); xAxis.normalize(); CrossProduct(yAxis, zAxis, xAxis); yAxis.normalize(); Float4x4 localMatrix = Float4x4( xAxis.x, xAxis.y, xAxis.z, lookerMatrix.padX, yAxis.x, yAxis.y, yAxis.z, lookerMatrix.padY, zAxis.x, zAxis.y, zAxis.z, lookerMatrix.padZ, lookerMatrix.WAxis.x, lookerMatrix.WAxis.y, lookerMatrix.WAxis.z, lookerMatrix.padW ); looker_transform->SetLocalMatrix(localMatrix); //LookAtSolution(); }
void SpotLight::ApplyLight() { // Set spot light position and direction Float3 dir3(GetWorldMatrixPtr()->_31, GetWorldMatrixPtr()->_32, GetWorldMatrixPtr()->_33); dir3.normalize(); XMFLOAT3 pos(&GetWorldMatrixPtr()->_41); cBufferData.spotLight.direction = XMFLOAT3(dir3.x, dir3.y, dir3.z); cBufferData.spotLight.position = pos; D3D11_MAPPED_SUBRESOURCE edit; Renderer::theContextPtr->Map(cBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &edit); memcpy(edit.pData, &cBufferData, sizeof(cBufferData)); Renderer::theContextPtr->Unmap(cBuffer, 0); Renderer::theContextPtr->VSSetConstantBuffers(cBufferData.SPOT_LIGHT_REGISTER_SLOT, 1, &cBuffer.p); Renderer::theContextPtr->PSSetConstantBuffers(cBufferData.SPOT_LIGHT_REGISTER_SLOT, 1, &cBuffer.p); // Check if the camera is inside the lit area Float3 toCamera = ViewPortManager::GetReference().GetActiveViewPosition() - *(Float3 *)&pos.x; toCamera.normalize(); if(toCamera.dotProduct(dir3) > cBufferData.spotLight.cutoff) techniqueNameOverride = "RenderSpotLightInside"; else techniqueNameOverride = "RenderSpotLightOutside"; AddToContextSet(); }
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; }
bool RayCastTriangle(const Float3& vStart,const Float3& vDir,const Float3& v0,const Float3& v1,const Float3& v2,float& fMaxDistance) { Float3 edge1 = v1 - v0; Float3 edge2 = v2 - v0; Float3 pvec = vDir.Cross(edge2); float det = edge1.Dot( pvec ); float u, v, t; Float3 tvec; if(det > 0){ tvec = vStart - v0; }else{ tvec = v0 - vStart; det = -det; } u = tvec.Dot(pvec); if(u<0.0f||u>det) return false; Float3 qvec = tvec.Cross(edge1); v = vDir.Dot(qvec); if(v<0.0f||u+v>det) return false; t = edge2.Dot(qvec)/det; if(t<0.0f||t>fMaxDistance) return false; fMaxDistance = t; //nor = cross(edge1,edge2); return true; };
Float3<T> Float3<T>::slerp(const Float3 &end, T percent) const { T theta = static_cast<T>(std::acos(this->dot(end) / (this->length() * end.length()))); T sinThetaRecip = static_cast<T>(1.0 / std::sin(theta)); T beginScale = static_cast<T>(std::sin((1.0 - percent) * theta) * sinThetaRecip); T endScale = static_cast<T>(std::sin(percent * theta) * sinThetaRecip); return this->scaledBy(beginScale) + end.scaledBy(endScale); }
void PS_Light::_update(Particle * p) { Float3 Position = p->Position; if (mParent->IsLocalSpace()) Position.TransformA(mParent->GetParent()->GetWorldTM()); mLight->SetPosition(Position); mLight->SetDirection(p->Direction); mLight->SetDiffuse(Float3(p->Color.r, p->Color.g, p->Color.b)); }
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 PS_Mesh::_update(Particle * p) { Float3 Position = p->Position; if (mParent->IsLocalSpace()) Position.TransformA(mParent->GetParent()->GetWorldTM()); mMesh->SetPosition(Position); mMesh->SetOpacity(p->Color.a); mMesh->SetRotationEx(p->Rotation); mMesh->SetScale(p->Size); mMesh->_updateTM(); int blendMode = mParent->GetBlendMode(); for (int i = 0; i < mMesh->GetSubMeshCount(); ++i) { SubMesh * submesh = mMesh->GetSubMesh(i); Material * mtl = submesh->GetMaterial(); mtl->diffuse = Float3(p->Color.r, p->Color.g, p->Color.b); if (mParent->_getTexture() != NULL) { mtl->maps[eMapType::DIFFUSE] = mParent->_getTexture(); } if (mParent->GetShaderEnable()) { mtl->depthMode = eDepthMode::N_LESS_EQUAL; if (blendMode == PS_BlendMode::ADD) { mtl->blendMode = eBlendMode::ADD; } else if (blendMode == PS_BlendMode::ALPHA_BLEND) { mtl->blendMode = eBlendMode::ALPHA_BLEND; } else if (blendMode == PS_BlendMode::COLOR_BLEND) { mtl->blendMode = eBlendMode::COLOR_BLEND; } else { mtl->blendMode = eBlendMode::OPACITY; mtl->depthMode = eDepthMode::LESS_EQUAL; } submesh->SetShaderFX(mParent->_getShaderFX()); submesh->SetRenderCallBack(eRenderCallBack::SHADER, mParent->GetShader().c_ptr()); } } }
void Physics::OnUpdate(IBehavior* invokingBehavior, IMessage* message) { Physics* pPhysics = (Physics*)invokingBehavior; const Aabb& objLocalAabb = pPhysics->gameObject->GetLocalAabb(); for(unsigned int i = 0; i < 3; ++i) { if( pPhysics->localAabb.min.v[i] != objLocalAabb.min.v[i] || pPhysics->localAabb.max.v[i] != objLocalAabb.max.v[i] ) { pPhysics->Initialize(); return; } } if( pPhysics->physicsFlags & GRAVITY ) { Attribute<bool>* groundedAttrib = (Attribute<bool>*)pPhysics->GetAttribute( PhysicsAttributes::GROUNDED_ATTRIB); if( groundedAttrib->value == false ) pPhysics->ApplyGravity(); } Float3 com(0.0f, 0.0f, 0.0f); for(unsigned int i = 0; i < pPhysics->m_X.size(); ++i) com += pPhysics->m_X[i]; com *= (1.0f / pPhysics->m_X.size()); pPhysics->ApplyVerlet(); pPhysics->ApplyConstraints(); Float3 newcom(0.0f, 0.0f, 0.0f); for(unsigned int i = 0; i < pPhysics->m_X.size(); ++i) newcom += pPhysics->m_X[i]; newcom *= (1.0f / pPhysics->m_X.size()); Float3 delta = newcom - com; if( delta.magnitude() > 0.25f ) { delta.normalize(); delta *= 0.25f; } pPhysics->gameObject->TranslateGlobal( delta ); }
void Actor::SetMoveDirection( const Float3& v ) { m_vMoveDir.x = v.x; m_vMoveDir.z = v.z; if(v.Length() <0.00001){ if(m_MoveState!=enAMS_NoMove){ m_pModel->SetActionState("stand.CAF"); m_MoveState = enAMS_NoMove; } }else{ float fRun = m_vMoveDir.Dot(m_vFaceDir); if(fRun > 0){ if(m_MoveState!=enAMS_CustomRun){ m_MoveState = enAMS_CustomRun; m_pModel->SetActionState("run.CAF"); } }else{ if(m_MoveState!=enAMS_CustomBack){ m_MoveState = enAMS_CustomBack; m_pModel->SetActionState("runback.CAF"); } } } }
void BoundingVolume::GetSplitAxis(const float *pointsPtr, unsigned int numPoints, Float3 &splitAxis, float &_min, float &_max) { Float3 vMin( FLT_MAX, FLT_MAX, FLT_MAX ); Float3 vMax( -FLT_MAX, -FLT_MAX, -FLT_MAX ); for(unsigned int i = 0; i < numPoints; i +=3 ) for(unsigned int j = 0; j < 3; ++j) { vMin.v[j] = min( vMin.v[j], pointsPtr[i+j] ); vMax.v[j] = max( vMax.v[j], pointsPtr[i+j] ); } unsigned int axis = 0; if( vMax.v[axis] - vMin.v[axis] < vMax.v[1] - vMin.v[1] ) axis = 1; if( vMax.v[axis] - vMin.v[axis] < vMax.v[2] - vMin.v[2] ) axis = 2; splitAxis.makeZero(); splitAxis.v[axis] = 1.0f; _min = vMin.v[axis]; _max = vMax.v[axis]; }
Float4x4 MatrixHelper::viewMatrix( const Float3 &pos, const Float3 &target, const Float3 &up ) { Float3 vz = ( target - pos ).normalizeND(); Float3 vx = up.cross( vz ).normalizeND(); Float3 vy = vz.cross( vx ).normalizeND(); float px = -pos.dot( vx ); float py = -pos.dot( vy ); float pz = -pos.dot( vz ); return Float4x4( vx.x, vy.x, vz.x, 0.0f, vx.y, vy.y, vz.y, 0.0f, vx.z, vy.z, vz.z, 0.0f, px, py, pz, 1.0f ); }
void SLSound::Update(const Float3 & listener) { float vol = mVolume * AudioSystem::Instance()->GetGlobalVolume(mCategory); if (mFlags & AUDIO_FLAG_3DSOUND) { Float3 d = mPosition - listener; float len = d.Length(); if (len > mAttenStart) { float k = (len - mAttenStart) * mInvAttenDist; k = 1.0f - Math::Clamp(k, 0.0f, 1.0f); vol *= k; } } float fade = 1; if (mFadeMode == FADE_IN) mFadeTime += Root::Instance()->GetFrameTime(); else if (mFadeMode == FADE_OUT) mFadeTime -= Root::Instance()->GetFrameTime(); mFadeTime = Math::Clamp(mFadeTime, 0.0f, SL_FADETIME); fade = mFadeTime / SL_FADETIME; vol *= fade; if (mVolumeAbs != vol) { SLmillibel volume = _getVolumeLevel(vol); (*mVolumeI)->SetVolumeLevel(mVolumeI, volume); (*mVolumeI)->SetMute(mVolumeI, vol > 0 ? FALSE : TRUE); mVolumeAbs = vol; } if (fade == 0 && mFadeMode == FADE_OUT) Stop(); else if (IsTimeOut()) Stop(); else if (i_thread == NULL) Track(); }
void Actor::Update( const FrameTime& frameTime ) { float fDot = acos(m_vFaceDir.Dot(Float3(0,0,1))); //Float3 vAxis = Float3(0,0,1).Cross(vDir).Normalize(); if(m_vFaceDir.x < 0){ fDot*=-1; } m_pNode->SetQuat(Float4(Float3(0,1,0),fDot)); if(m_uiLowBodyBoneIndex!=0xffffffff){ if(m_vMoveDir.Length() < 0.5){ m_pModel->DisableBoneExtraRotate(m_uiLowBodyBoneIndex); }else{ Float3 vNewMoveDir = m_vMoveDir; float fRun = vNewMoveDir.Dot(m_vFaceDir); if(fRun <0){ vNewMoveDir*=-1;//m_pModel->EnableBoneExtraRotate(uiIndex,Float4(Float3(0,0,-1),fFootDot)); } float fFootAngle = acos(vNewMoveDir.Dot(m_vFaceDir)); if(fFootAngle < 0.00001f){ m_pModel->EnableBoneExtraRotate(m_uiLowBodyBoneIndex,Float4(Float3(0,0,1),0)); }else{ Float3 vAxis = m_vFaceDir.Cross(vNewMoveDir).Normalize(); m_pModel->EnableBoneExtraRotate(m_uiLowBodyBoneIndex,Float4(Float3(0,0,vAxis.y),-fFootAngle)); } } } //UpdateSkill U32 uiSkillCount = m_vecSkill.size(); for(U32 i=0;i<uiSkillCount;i++){ Skill* pSkill = m_vecSkill[i]; if(pSkill!=NULL){ pSkill->Update(frameTime,this); } } Move(frameTime.fTimeDelta); }
void HardAttach::Update(void) { static const EDGameCore::RegistrationId MSG_CLAMP = EDGameCore::Message("MSG_CLAMP").messageId; if( targetId != 0 ) { EDGameCore::GameObject* targetObj = EDGameCore::GameObject::GetGameObjectInstance(targetId); if( targetObj == 0 ) { targetId = 0; return; } Float4x4 newMat = GetTransform()->GetLocalMatrix(); TransformPoint( newMat.WAxis, offset, targetObj->GetTransform()->GetWorldMatrix() ); unsigned int clampToId = 0; if( clamp ) { Float3 startPos = targetObj->GetTransform()->GetWorldMatrix().WAxis; Float3 delta = newMat.WAxis - startPos; float deltaLen = delta.magnitude(); Float3 deltaN = delta * (1.0f / deltaLen); EDGameCore::RayHit rayHit; if( EDGameCore::Physics::RayCast( startPos, deltaN, deltaLen, GetGameObject()->GetLayerMask(), rayHit ) ) { newMat.WAxis = rayHit.Point; clampToId = rayHit.collider->GetGameObject()->GetInstanceId(); } } GetTransform()->SetLocalMatrix( newMat ); if( clampToId != 0 ) GetGameObject()->OnMessage( EDGameCore::MessageT<unsigned int>(MSG_CLAMP, clampToId) ); } }
void BuildSphere(Sphere& out, const Sphere& a, const Sphere& b) { Float3 d = b.center - a.center; float distSq = d.squaredMagnitude(); if( (b.radius - a.radius)*(b.radius - a.radius) >= distSq ) { if( b.radius >= a.radius ) out = b; else out = a; } else { float dist = sqrtf(distSq); out.radius = (dist + a.radius + b.radius) * 0.5f; out.center = a.center; if( dist > 0.001f ) out.center += d * ((out.radius - a.radius) / dist); } }
void RenderController::SetPerCameraShaderVariables() { ViewPortManager &vpm = ViewPortManager::GetReference(); XMVECTOR det; cbPerCamera camBuffer; camBuffer.gViewProj = *(XMFLOAT4X4 *)&ViewPortManager::GetReference().GetActiveViewProjection(); camBuffer.gCameraPos = XMFLOAT3(vpm.GetActiveViewPosition().v); Float3 camDir = vpm.GetActiveViewForward(); camDir.normalize(); camBuffer.gCameraDir = XMFLOAT3(camDir.v); camBuffer.gFarDist = vpm.GetActiveViewFarClip(); //camBuffer.gNearDist = vpm.GetActiveViewNearClip(); float nearDist = vpm.GetActiveViewNearClip(); camBuffer.gScreenSize.x = (float)Renderer::GetResolutionWidth(); camBuffer.gScreenSize.y = (float)Renderer::GetResolutionHeight(); XMStoreFloat4x4(&camBuffer.gInvViewProj, XMMatrixInverse(&det, XMLoadFloat4x4(&camBuffer.gViewProj))); camBuffer.gPlaneX = -camBuffer.gFarDist / (camBuffer.gFarDist - nearDist); camBuffer.gPlaneY = -camBuffer.gFarDist * nearDist / (camBuffer.gFarDist - nearDist); D3D11_MAPPED_SUBRESOURCE edit; Renderer::theContextPtr->Map(cameraCBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &edit); memcpy(edit.pData, &camBuffer, sizeof(camBuffer)); Renderer::theContextPtr->Unmap(cameraCBuffer, 0); Renderer::theContextPtr->VSSetConstantBuffers(camBuffer.REGISTER_SLOT, 1, &cameraCBuffer.p); Renderer::theContextPtr->PSSetConstantBuffers(camBuffer.REGISTER_SLOT, 1, &cameraCBuffer.p); Renderer::theContextPtr->GSSetConstantBuffers(camBuffer.REGISTER_SLOT, 1, &cameraCBuffer.p); Renderer::theContextPtr->HSSetConstantBuffers(camBuffer.REGISTER_SLOT, 1, &cameraCBuffer.p); Renderer::theContextPtr->DSSetConstantBuffers(camBuffer.REGISTER_SLOT, 1, &cameraCBuffer.p); }
void Physics::OnApplyReaction(IBehavior* invokingBehavior, IMessage* message) { Physics* pPhysics = (Physics*)invokingBehavior; MessageT<CollisionContact>* msg = (MessageT<CollisionContact>*)message; Float3 velocity = pPhysics->m_X[0] - pPhysics->m_OldX[0]; velocity += msg->value.m_ContactNormal * msg->value.m_PenetrationDepth; float ndotv = DotProduct( msg->value.m_ContactNormal, velocity ); Float3 normalVelocity = msg->value.m_ContactNormal * ndotv; Float3 tangentialVelocity = velocity - normalVelocity; Float3 oldTV = tangentialVelocity; float m_COF = 0.0f; float m_COR = 0.0f; float tvMagSq = DotProduct(tangentialVelocity, tangentialVelocity); if( tvMagSq > 0.0f ) { float tvMag = sqrt(tvMagSq); tangentialVelocity *= (1.0f / tvMag); Float3 tvNorm = tangentialVelocity; tangentialVelocity *= max( 0.0f, tvMag - msg->value.m_PenetrationDepth*m_COF); } else tangentialVelocity.makeZero(); pPhysics->gameObject->TranslateGlobal( velocity ); pPhysics->m_X[0] = pPhysics->m_OldX[0] + velocity; pPhysics->m_OldX[0] = pPhysics->m_X[0] - tangentialVelocity - normalVelocity * m_COR; //pPhysics->m_OldX[0] += (oldTV - tangentialVelocity); //pPhysics->m_OldX[0] = pPhysics->m_X[0] - tangentialVelocity - normalVelocity; //pPhysics->m_OldX[0] -= normalVelocity; }
BSphere MergeBoundingSpheres(const std::vector<BSphere> &bspheres) { BSphere sphere = bspheres[0]; for (uint32 i = 1; i < bspheres.size(); i++) { BSphere &sphere1 = sphere; const BSphere &sphere2 = bspheres[i]; Float3 sphere2Center(sphere2.Center); Float3 sphere1Center(sphere1.Center); Float3 difference = sphere2Center - sphere1Center; float length = difference.Length(); float radius = sphere1.Radius; float radius2 = sphere2.Radius; if (radius + radius2 >= length) { if (radius - radius2 >= length) return sphere1; if (radius2 - radius >= length) return sphere2; } Float3 vector = difference * (1.0f / length); float min = Min(-radius, length - radius2); float max = (Max(radius, length + radius2) - min) * 0.5f; sphere.Center = *(XMFLOAT3 *)&(sphere1Center + vector * (max + min)); sphere.Radius = max; } return sphere; }
Float3 Float3::Perpendicular(const Float3& vec) { Assert_(vec.Length() >= 0.00001f); Float3 perp; float x = std::abs(vec.x); float y = std::abs(vec.y); float z = std::abs(vec.z); float minVal = std::min(x, y); minVal = std::min(minVal, z); if(minVal == x) perp = Float3::Cross(vec, Float3(1.0f, 0.0f, 0.0f)); else if(minVal == y) perp = Float3::Cross(vec, Float3(0.0f, 1.0f, 0.0f)); else perp = Float3::Cross(vec, Float3(0.0f, 0.0f, 1.0f)); return Float3::Normalize(perp); }
void Frustum::SetDir( const Float3& dir ){ m_vDirection = dir.NormalizeCopy(); m_bDirty = true; }
void Float4x4::SetRow(int row, const Float3 &rowVector, float m_r3) { SetRow( row, rowVector.X(), rowVector.Y(), rowVector.Z(), m_r3 ); }
void Float4x4::SetTranslatePart(const Float3 &offset) { m_value.SetTranslatePart(offset.ToImpl()); }
Float3 Float4x4::TransformDir(const Float3 &directionVector) const { return TransformDir(directionVector.X(), directionVector.Y(), directionVector.Z()); }
Float3 Float4x4::TransformPos(const Float3 &pointVector) const { return TransformPos(pointVector.X(), pointVector.Y(), pointVector.Z()); }
// Renders meshes using cascaded shadow mapping void MeshRenderer::RenderSunShadowMap(ID3D11DeviceContext* context, const Camera& camera) { PIXEvent event(L"Sun Shadow Map Rendering"); const float MinDistance = reductionDepth.x; const float MaxDistance = reductionDepth.y; // Compute the split distances based on the partitioning mode float CascadeSplits[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; { float lambda = 1.0f; float nearClip = camera.NearClip(); float farClip = camera.FarClip(); float clipRange = farClip - nearClip; float minZ = nearClip + MinDistance * clipRange; float maxZ = nearClip + MaxDistance * clipRange; float range = maxZ - minZ; float ratio = maxZ / minZ; for(uint32 i = 0; i < NumCascades; ++i) { float p = (i + 1) / static_cast<float>(NumCascades); float log = minZ * std::pow(ratio, p); float uniform = minZ + range * p; float d = lambda * (log - uniform) + uniform; CascadeSplits[i] = (d - nearClip) / clipRange; } } Float3 c0Extents; Float4x4 c0Matrix; const Float3 lightDir = AppSettings::SunDirection; // Render the meshes to each cascade for(uint32 cascadeIdx = 0; cascadeIdx < NumCascades; ++cascadeIdx) { PIXEvent cascadeEvent((L"Rendering Shadow Map Cascade " + ToString(cascadeIdx)).c_str()); // Set the viewport SetViewport(context, ShadowMapSize, ShadowMapSize); // Set the shadow map as the depth target ID3D11DepthStencilView* dsv = sunShadowDepthMap.DSView; ID3D11RenderTargetView* nullRenderTargets[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = { NULL }; context->OMSetRenderTargets(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT, nullRenderTargets, dsv); context->ClearDepthStencilView(dsv, D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL, 1.0f, 0); // Get the 8 points of the view frustum in world space XMVECTOR frustumCornersWS[8] = { XMVectorSet(-1.0f, 1.0f, 0.0f, 1.0f), XMVectorSet( 1.0f, 1.0f, 0.0f, 1.0f), XMVectorSet( 1.0f, -1.0f, 0.0f, 1.0f), XMVectorSet(-1.0f, -1.0f, 0.0f, 1.0f), XMVectorSet(-1.0f, 1.0f, 1.0f, 1.0f), XMVectorSet( 1.0f, 1.0f, 1.0f, 1.0f), XMVectorSet( 1.0f, -1.0f, 1.0f, 1.0f), XMVectorSet(-1.0f, -1.0f, 1.0f, 1.0f), }; float prevSplitDist = cascadeIdx == 0 ? MinDistance : CascadeSplits[cascadeIdx - 1]; float splitDist = CascadeSplits[cascadeIdx]; XMVECTOR det; XMMATRIX invViewProj = XMMatrixInverse(&det, camera.ViewProjectionMatrix().ToSIMD()); for(uint32 i = 0; i < 8; ++i) frustumCornersWS[i] = XMVector3TransformCoord(frustumCornersWS[i], invViewProj); // Get the corners of the current cascade slice of the view frustum for(uint32 i = 0; i < 4; ++i) { XMVECTOR cornerRay = XMVectorSubtract(frustumCornersWS[i + 4], frustumCornersWS[i]); XMVECTOR nearCornerRay = XMVectorScale(cornerRay, prevSplitDist); XMVECTOR farCornerRay = XMVectorScale(cornerRay, splitDist); frustumCornersWS[i + 4] = XMVectorAdd(frustumCornersWS[i], farCornerRay); frustumCornersWS[i] = XMVectorAdd(frustumCornersWS[i], nearCornerRay); } // Calculate the centroid of the view frustum slice XMVECTOR frustumCenterVec = XMVectorZero(); for(uint32 i = 0; i < 8; ++i) frustumCenterVec = XMVectorAdd(frustumCenterVec, frustumCornersWS[i]); frustumCenterVec = XMVectorScale(frustumCenterVec, 1.0f / 8.0f); Float3 frustumCenter = frustumCenterVec; // Pick the up vector to use for the light camera Float3 upDir = camera.Right(); Float3 minExtents; Float3 maxExtents; { // Create a temporary view matrix for the light Float3 lightCameraPos = frustumCenter; Float3 lookAt = frustumCenter - lightDir; XMMATRIX lightView = XMMatrixLookAtLH(lightCameraPos.ToSIMD(), lookAt.ToSIMD(), upDir.ToSIMD()); // Calculate an AABB around the frustum corners XMVECTOR mins = XMVectorSet(REAL_MAX, REAL_MAX, REAL_MAX, REAL_MAX); XMVECTOR maxes = XMVectorSet(-REAL_MAX, -REAL_MAX, -REAL_MAX, -REAL_MAX); for(uint32 i = 0; i < 8; ++i) { XMVECTOR corner = XMVector3TransformCoord(frustumCornersWS[i], lightView); mins = XMVectorMin(mins, corner); maxes = XMVectorMax(maxes, corner); } minExtents = mins; maxExtents = maxes; } // Adjust the min/max to accommodate the filtering size float scale = (ShadowMapSize + FilterSize) / static_cast<float>(ShadowMapSize); minExtents.x *= scale; minExtents.y *= scale; maxExtents.x *= scale; maxExtents.x *= scale; Float3 cascadeExtents = maxExtents - minExtents; // Get position of the shadow camera Float3 shadowCameraPos = frustumCenter + lightDir * -minExtents.z; // Come up with a new orthographic camera for the shadow caster OrthographicCamera shadowCamera(minExtents.x, minExtents.y, maxExtents.x, maxExtents.y, 0.0f, cascadeExtents.z); shadowCamera.SetLookAt(shadowCameraPos, frustumCenter, upDir); // Draw the mesh with depth only, using the new shadow camera RenderDepth(context, shadowCamera, true, false); // Apply the scale/offset matrix, which transforms from [-1,1] // post-projection space to [0,1] UV space XMMATRIX texScaleBias; texScaleBias.r[0] = XMVectorSet(0.5f, 0.0f, 0.0f, 0.0f); texScaleBias.r[1] = XMVectorSet(0.0f, -0.5f, 0.0f, 0.0f); texScaleBias.r[2] = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f); texScaleBias.r[3] = XMVectorSet(0.5f, 0.5f, 0.0f, 1.0f); XMMATRIX shadowMatrix = shadowCamera.ViewProjectionMatrix().ToSIMD(); shadowMatrix = XMMatrixMultiply(shadowMatrix, texScaleBias); // Store the split distance in terms of view space depth const float clipDist = camera.FarClip() - camera.NearClip(); shadowConstants.Data.CascadeSplits[cascadeIdx] = camera.NearClip() + splitDist * clipDist; if(cascadeIdx == 0) { c0Extents = cascadeExtents; c0Matrix = shadowMatrix; shadowConstants.Data.ShadowMatrix = XMMatrixTranspose(shadowMatrix); shadowConstants.Data.CascadeOffsets[0] = Float4(0.0f, 0.0f, 0.0f, 0.0f); shadowConstants.Data.CascadeScales[0] = Float4(1.0f, 1.0f, 1.0f, 1.0f); } else { // Calculate the position of the lower corner of the cascade partition, in the UV space // of the first cascade partition Float4x4 invCascadeMat = Float4x4::Invert(shadowMatrix); Float3 cascadeCorner = Float3::Transform(Float3(0.0f, 0.0f, 0.0f), invCascadeMat); cascadeCorner = Float3::Transform(cascadeCorner, c0Matrix); // Do the same for the upper corner Float3 otherCorner = Float3::Transform(Float3(1.0f, 1.0f, 1.0f), invCascadeMat); otherCorner = Float3::Transform(otherCorner, c0Matrix); // Calculate the scale and offset Float3 cascadeScale = Float3(1.0f, 1.0f, 1.f) / (otherCorner - cascadeCorner); shadowConstants.Data.CascadeOffsets[cascadeIdx] = Float4(-cascadeCorner, 0.0f); shadowConstants.Data.CascadeScales[cascadeIdx] = Float4(cascadeScale, 1.0f); } ConvertToEVSM(context, cascadeIdx, shadowConstants.Data.CascadeScales[cascadeIdx].To3D()); } }
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); }