/*** Crealysm 3D engine, by Cristiaan Kop - updated 21-03-2015 ***/ /*** ============================================================================== ***/ /*** NAMESPACE: CREALYSM_D3DRENDERER ***/ /*** cpp file with Crealysm d3d camera implementation, direct3d9 ***/ #include "Crealysm_d3dcam.h" #include #include "Crealysm_math.h" #include "Crealysm_dxmath.h" using namespace Crealysm_math; using namespace Crealysm_dxmath; using namespace DirectX; namespace Crealysm_d3drenderer { /**************************************************************************************/ /*** CONSTRUCTOR ***/ /*** ==> usage: when creating a CD3dcam ***/ /*** ==> sets all variables in the CD3dcam object to initial and parameter values ***/ /**************************************************************************************/ CD3dcam::CD3dcam() { mRight = XMFLOAT3(1.0f,0.0f,0.0f); mUp = XMFLOAT3(0.0f,1.0f,0.0f); mLook = XMFLOAT3(0.0f,0.0f,1.0f); } /**************************************************************************************/ /*** DESTRUCTOR ***/ /*** ==> usage: when CD3dcam object is not needed anymore ***/ /*** ==> releases nothing yet ***/ /**************************************************************************************/ CD3dcam::~CD3dcam() { // nothing yet } /**************************************************************************************/ /*** INITALIZE ***/ /*** ==> usage: when the camera's position and rotation needs to be initalized ***/ /*** ==> set the (initial) position and rotation of the camera ***/ /**************************************************************************************/ void CD3dcam::Initialize(const XMFLOAT3 &pPos, const XMFLOAT3 &pRot) { mPosition = pPos; mPitch = pRot.x; mYaw = pRot.y; mRoll = pRot.z; } /**************************************************************************************/ /*** CALCULATE PROJECTIONMATRIX ***/ /*** ==> usage: when the field of view, near or far planges (mostly only at init) ***/ /*** ==> calculates projectionmatrix using fov, near, far and screen dimensions ***/ /**************************************************************************************/ bool CD3dcam::CalculateProjectionMatrix(const float pFov, const float pNear, const float pFar, const int pSw, const int pSh) { XMMATRIX xmMatProjection = XMMatrixPerspectiveFovLH(XMConvertToRadians(pFov), (FLOAT)pSw / (FLOAT)pSh, pNear, pFar); XMStoreFloat4x4(&mMatProjection, xmMatProjection); return true; } /**************************************************************************************/ /*** UPDATE ***/ /*** ==> usage: for each frame, at beginning of rendering (unless static cam) ***/ /*** ==> calls the functions to calculate the viewmatrix and frustum ***/ /**************************************************************************************/ void CD3dcam::Update() { CalculateViewMatrix(); CalculateFrustum(); // update inverse view matrix XMMATRIX xmViewMat = XMLoadFloat4x4(&mMatView); xmViewMat = XMMatrixInverse(NULL, xmViewMat); XMStoreFloat4x4(&mMatViewInverse, xmViewMat); } /**************************************************************************************/ /*** FREELOOK ***/ /*** ==> usage: when the mouse is moved for looking around ***/ /*** ==> calculates changed camera rotations around X and Y axis ***/ /**************************************************************************************/ void CD3dcam::FreeLook(const long pMousePosX, const long pMousePosY, const float pLookSpeed) { mYaw += (float)pMousePosX * pLookSpeed; mYaw = restrictDegAngleTo360Range(mYaw); mPitch += (float)pMousePosY * pLookSpeed; mPitch = restrictDegAngleTo360Range(mPitch); } /**************************************************************************************/ /*** SET POSITION (1) ***/ /*** ==> usage: when the camera pos needs to be changed outside the CD3dcam class ***/ /*** ==> updates the mPosition with given input XMFLOAT3 ***/ /**************************************************************************************/ void CD3dcam::SetPosition(const XMFLOAT3 &pPos) { mLastPosition = mPosition; mPosition = pPos; } /**************************************************************************************/ /*** SET POSITION (2) ***/ /*** ==> usage: when the camera pos needs to be changed outside the CD3dcam class ***/ /*** ==> updates the mPosition with given input Crealysm_math::VECTOR3 ***/ /**************************************************************************************/ void CD3dcam::SetPosition(const VECTOR3 &pPos) { mLastPosition = mPosition; mPosition = XMFLOAT3(pPos.x, pPos.y, pPos.z); } /**************************************************************************************/ /*** RESET ROT ***/ /*** ==> usage: when camera rotations need to be reset ***/ /*** ==> sets yaw, pitch and roll euler angles to 0.0f ***/ /**************************************************************************************/ void CD3dcam::ResetRot() { mPitch = 0.0f; // X mYaw = 0.0f; // Y mRoll = 0.0f; // Z } /**************************************************************************************/ /*** ROTATE (3 floats) ***/ /*** ==> usage: when camera needs to be rotated with euler angles ***/ /*** ==> sets the pitch, yaw and roll to given input parameters ***/ /**************************************************************************************/ void CD3dcam::Rotate(const float pPitch, const float pYaw, const float pRoll) { mPitch += pPitch; // X mPitch = restrictDegAngleTo360Range(mPitch); mYaw += pYaw; // Y mYaw = restrictDegAngleTo360Range(mYaw); mRoll += pRoll; // Z mRoll = restrictDegAngleTo360Range(mRoll); } /**************************************************************************************/ /*** ROTATE (VECTOR3) ***/ /*** ==> usage: when camera needs to be rotated with euler angles ***/ /*** ==> sets the pitch, yaw and roll to given input parameters - VECTOR3 ***/ /**************************************************************************************/ void CD3dcam::Rotate(const VECTOR3 &pRot) { mPitch += pRot.x; // X mPitch = restrictDegAngleTo360Range(mPitch); mYaw += pRot.y; // Y mYaw = restrictDegAngleTo360Range(mYaw); mRoll += pRot.z; // Z mRoll = restrictDegAngleTo360Range(mRoll); } /**************************************************************************************/ /*** ROTATE ABS ***/ /*** ==> usage: when camera needs to be rotated to absolute angles ***/ /*** ==> sets the pitch, yaw and roll to given input - VECTOR3, i.e. animations ***/ /**************************************************************************************/ void CD3dcam::RotateAbs(const VECTOR3 &pRot) { mPitch = pRot.x; // X mYaw = pRot.y; // Y mRoll = pRot.z; // Z // mPitch = restrictDegAngleTo360Range(mPitch); // mYaw = restrictDegAngleTo360Range(mYaw); // mRoll = restrictDegAngleTo360Range(mRoll); } /**************************************************************************************/ /*** MOVE ***/ /*** ==> usage: when camera moves, based on input movement vector ***/ /*** ==> calls the private move up/down etc. functions to move using up/look/right ***/ /**************************************************************************************/ void CD3dcam::Move(const Crealysm_math::VECTOR3 &pMovement) { mLastPosition = mPosition; MoveForwardBackward(pMovement.z); MoveLeftRight(pMovement.x); MoveUpDown(pMovement.y); } /**************************************************************************************/ /*** MOVE NO HEADING ***/ /*** ==> usage: when camera moves, both X, Y and Z movement => no heading ***/ /*** ==> update the camera position ***/ /**************************************************************************************/ void CD3dcam::MoveNoHeading(const Crealysm_math::VECTOR3 &pMovement) { mLastPosition = mPosition; mPosition.x += pMovement.x; mPosition.y += pMovement.y; mPosition.z += pMovement.z; } /**************************************************************************************/ /*** PITCH ***/ /*** ==> usage: when camera rotates around the X-axis ***/ /*** ==> updates the rotation value and prevents stall at 360 degrees ***/ /**************************************************************************************/ void CD3dcam::Pitch(const float pAmount) { mPitch += pAmount; mPitch = restrictDegAngleTo360Range(mPitch); } /**************************************************************************************/ /*** YAW ***/ /*** ==> usage: when camera rotates around the Y-axis ***/ /*** ==> updates the rotation value and prevents stall at 360 degrees ***/ /**************************************************************************************/ void CD3dcam::Yaw(const float pAmount) { mYaw += pAmount; mYaw = restrictDegAngleTo360Range(mYaw); } /**************************************************************************************/ /*** ROLL ***/ /*** ==> usage: when camera rotates around the Z-axis ***/ /*** ==> updates the rotation value and prevents stall at 360 degrees ***/ /**************************************************************************************/ void CD3dcam::Roll(const float pAmount) { mRoll += pAmount; mRoll = restrictDegAngleTo360Range(mRoll); } /**************************************************************************************/ /*** CALCULATE VIEWMATRIX ***/ /*** ==> usage: whenever the camera looks another way or moves around ***/ /*** ==> calculates viewmatrix using up, look and right vectors ***/ /**************************************************************************************/ void CD3dcam::CalculateViewMatrix() { XMVECTOR xmRight = { 1.0f, 0.0f, 0.0f }; XMVECTOR xmUp = { 0.0f, 1.0f, 0.0f }; XMVECTOR xmLook = { 0.0f, 0.0f, 1.0f }; XMMATRIX xmYawMatrix = XMMatrixRotationAxis(xmUp, XMConvertToRadians(mYaw)); // Y xmLook = XMVector3TransformCoord(xmLook, xmYawMatrix); xmRight = XMVector3TransformCoord(xmRight, xmYawMatrix); XMMATRIX xmPitchMatrix = XMMatrixRotationAxis(xmRight, XMConvertToRadians(mPitch)); // X xmLook = XMVector3TransformCoord(xmLook, xmPitchMatrix); xmUp = XMVector3TransformCoord(xmUp, xmPitchMatrix); XMMATRIX xmRollMatrix = XMMatrixRotationAxis(xmLook, XMConvertToRadians(mRoll)); // Z xmRight = XMVector3TransformCoord(xmRight, xmRollMatrix); xmUp = XMVector3TransformCoord(xmUp, xmRollMatrix); XMStoreFloat3(&mRight, xmRight); XMStoreFloat3(&mUp, xmUp); XMStoreFloat3(&mLook, xmLook); XMVECTOR xmCamPos = XMLoadFloat3(&mPosition); XMMATRIX xmMatView = XMMatrixIdentity(); xmMatView = XMMatrixSet(mRight.x, mUp.x, mLook.x, 0, mRight.y, mUp.y, mLook.y, 0, mRight.z, mUp.z, mLook.z, 0, -XMVectorGetX(XMVector3Dot(xmCamPos, xmRight)), -XMVectorGetX(XMVector3Dot(xmCamPos, xmUp)), -XMVectorGetX(XMVector3Dot(xmCamPos, xmLook)), 1); XMStoreFloat4x4(&mMatView, xmMatView); } /**************************************************************************************/ /*** CALCULATE FRUSTUM ***/ /*** ==> usage: after camera moves/rotates, mostly for each rendered frame ***/ /*** ==> update ViewProjection matrix and calculates view frustum planes ***/ /**************************************************************************************/ void CD3dcam::CalculateFrustum() { XMMATRIX xmMatView = XMLoadFloat4x4(&mMatView); XMMATRIX xmMatProjection = XMLoadFloat4x4(&mMatProjection); XMMATRIX xmMatViewProjection = XMMatrixMultiply(xmMatView, xmMatProjection); XMStoreFloat4x4(&mMatViewProjection, xmMatViewProjection); // left plane mFrustumPlane[0].x = mMatViewProjection._14 + mMatViewProjection._11; mFrustumPlane[0].y = mMatViewProjection._24 + mMatViewProjection._21; mFrustumPlane[0].z = mMatViewProjection._34 + mMatViewProjection._31; mFrustumPlane[0].w = mMatViewProjection._44 + mMatViewProjection._41; // right plane mFrustumPlane[1].x = mMatViewProjection._14 - mMatViewProjection._11; mFrustumPlane[1].y = mMatViewProjection._24 - mMatViewProjection._21; mFrustumPlane[1].z = mMatViewProjection._34 - mMatViewProjection._31; mFrustumPlane[1].w = mMatViewProjection._44 - mMatViewProjection._41; // top plane mFrustumPlane[2].x = mMatViewProjection._14 - mMatViewProjection._12; mFrustumPlane[2].y = mMatViewProjection._24 - mMatViewProjection._22; mFrustumPlane[2].z = mMatViewProjection._34 - mMatViewProjection._32; mFrustumPlane[2].w = mMatViewProjection._44 - mMatViewProjection._42; // bottom plane mFrustumPlane[3].x = mMatViewProjection._14 + mMatViewProjection._12; mFrustumPlane[3].y = mMatViewProjection._24 + mMatViewProjection._22; mFrustumPlane[3].z = mMatViewProjection._34 + mMatViewProjection._32; mFrustumPlane[3].w = mMatViewProjection._44 + mMatViewProjection._42; // near plane mFrustumPlane[4].x = mMatViewProjection._13; mFrustumPlane[4].y = mMatViewProjection._23; mFrustumPlane[4].z = mMatViewProjection._33; mFrustumPlane[4].w = mMatViewProjection._43; // far plane mFrustumPlane[5].x = mMatViewProjection._14 - mMatViewProjection._13; mFrustumPlane[5].y = mMatViewProjection._24 - mMatViewProjection._23; mFrustumPlane[5].z = mMatViewProjection._34 - mMatViewProjection._33; mFrustumPlane[5].w = mMatViewProjection._44 - mMatViewProjection._43; for(int i=0;i<6;++i) { XMVECTOR xmPlane = XMLoadFloat4(&mFrustumPlane[i]); xmPlane = XMPlaneNormalizeEst(xmPlane); XMStoreFloat4(&mFrustumPlane[i], xmPlane); // calculate sign (+ or -) per frustum plane, to find P/N vertex in AABB checks if(mFrustumPlane[i].x >= 0) mFrustumPlaneSign[i].x = 1.0f; if(mFrustumPlane[i].x < 0) mFrustumPlaneSign[i].x = -1.0f; if(mFrustumPlane[i].y >= 0) mFrustumPlaneSign[i].y = 1.0f; if(mFrustumPlane[i].y < 0) mFrustumPlaneSign[i].y = -1.0f; if(mFrustumPlane[i].z >= 0) mFrustumPlaneSign[i].z = 1.0f; if(mFrustumPlane[i].z < 0) mFrustumPlaneSign[i].z = -1.0f; } } /**************************************************************************************/ /*** MOVE FORWARD BACKWARD ***/ /*** ==> usage: when camera moves forward or backward ***/ /*** ==> calculates the changed X and Z camera position, based on movement value ***/ /**************************************************************************************/ void CD3dcam::MoveForwardBackward(const float pAmount) { XMVECTOR xmPos = XMLoadFloat3(&mPosition); //xmPos += (XMLoadFloat3(&mLook) * pAmount); // 'flying' allowed, 6 DOF // to disable 'FLYING', use: XMVECTOR tempLook = { mLook.x, 0.0f, mLook.z }; xmPos += tempLook * pAmount; XMStoreFloat3(&mPosition, xmPos); } /**************************************************************************************/ /*** MOVE LEFT RIGHT ***/ /*** ==> usage: when camera strafes to the left or right ***/ /*** ==> calculates the changed X and Z camera position, based on movement value ***/ /**************************************************************************************/ void CD3dcam::MoveLeftRight(const float pAmount) { XMVECTOR xmPos = XMLoadFloat3(&mPosition); xmPos += (XMLoadFloat3(&mRight) * pAmount); XMStoreFloat3(&mPosition, xmPos); } /**************************************************************************************/ /*** MOVE UP DOWN ***/ /*** ==> usage: when camera moves up or down ***/ /*** ==> calculates changed camera pos, based on param value using up vector ***/ /**************************************************************************************/ void CD3dcam::MoveUpDown(const float pAmount) { mPosition.y += pAmount; } /**************************************************************************************/ /*** GET POSITION CONST ***/ /*** ==> usage: when the camera pos is needed outside the CD3dcam class ***/ /*** ==> returns a XMFLOAT3 with the current camera position ***/ /**************************************************************************************/ XMFLOAT3 CD3dcam::GetPosition() const { return mPosition; } /**************************************************************************************/ /*** GET LAST POSITION CONST ***/ /*** ==> usage: when the last camera pos is needed outside the CD3dcam class ***/ /*** ==> returns a XMFLOAT3 with the last camera position ***/ /**************************************************************************************/ XMFLOAT3 CD3dcam::GetLastPosition() const { return mLastPosition; } /**************************************************************************************/ /*** GET POSITION V3 (vector3) CONST ***/ /*** ==> usage: when the camera pos is needed outside the CD3dcam class ***/ /*** ==> returns a VECTOR3 with the current camera position ***/ /**************************************************************************************/ VECTOR3 CD3dcam::GetPositionV3() const { return VECTOR3(mPosition.x, mPosition.y, mPosition.z); } /**************************************************************************************/ /*** GET LAST POSITION V3 (vector3) CONST ***/ /*** ==> usage: when the camera last pos is needed outside the CD3dcam class ***/ /*** ==> returns a VECTOR3 with the last camera position ***/ /**************************************************************************************/ VECTOR3 CD3dcam::GetLastPositionV3() const { return VECTOR3(mLastPosition.x, mLastPosition.y, mLastPosition.z); } /**************************************************************************************/ /*** GET ROT CONST ***/ /*** ==> usage: when the camera rotation XYZ is needed outside the CD3dcam class ***/ /*** ==> returns a XMFLOAT3 with the current camera rot angles ***/ /**************************************************************************************/ XMFLOAT3 CD3dcam::GetRot() const { return XMFLOAT3(mPitch, mYaw, mRoll); } /**************************************************************************************/ /*** GET ROT V3 CONST ***/ /*** ==> usage: when the camera rotation XYZ is needed outside the CD3dcam class ***/ /*** ==> returns a VECTOR3 with the current camera rot angles ***/ /**************************************************************************************/ VECTOR3 CD3dcam::GetRotV3() const { return VECTOR3(mPitch, mYaw, mRoll); } /**************************************************************************************/ /*** GET VIEW MATRIX CONST ***/ /*** ==> usage: when the camera view matrix is needed outside the class ***/ /*** ==> returns a XMFLOAT4X4A with the matrix, by value ***/ /**************************************************************************************/ XMFLOAT4X4 CD3dcam::GetViewMatrix() const { return mMatView; } /**************************************************************************************/ /*** GET PROJ MATRIX CONST ***/ /*** ==> usage: when the camera projection matrix is needed outside the class ***/ /*** ==> returns a XMFLOAT4X4A with the matrix, by value ***/ /**************************************************************************************/ XMFLOAT4X4 CD3dcam::GetProjMatrix() const { return mMatProjection; } /**************************************************************************************/ /*** GET VIEW PROJECTION MATRIX CONST ***/ /*** ==> usage: when the camera view-projection matrix is needed outside the class ***/ /*** ==> returns a XMFLOAT4X4 with the matrix, by value ***/ /**************************************************************************************/ XMFLOAT4X4 CD3dcam::GetViewProjMatrix() const { return mMatViewProjection; } /**************************************************************************************/ /*** GET INVERSE VIEW MATRIX CONST ***/ /*** ==> usage: when the camera's inverse view matrix is needed outside the class ***/ /*** ==> returns a XMFLOAT4X4 with the matrix, by value ***/ /**************************************************************************************/ XMFLOAT4X4 CD3dcam::GetInverseViewMatrix() const { return mMatViewInverse; } /**************************************************************************************/ /*** GET PITCH CONST ***/ /*** ==> usage: when camera X rotation angle is needed ***/ /*** ==> returns the actual PITCH value of the camera ***/ /**************************************************************************************/ float CD3dcam::GetPitch() const { return mPitch; } /**************************************************************************************/ /*** GET YAW CONST ***/ /*** ==> usage: when camera Y rotation angle is needed ***/ /*** ==> returns the actual YAW value of the camera ***/ /**************************************************************************************/ float CD3dcam::GetYaw() const { return mYaw; } /**************************************************************************************/ /*** GET ROLL CONST ***/ /*** ==> usage: when camera Z rotation angle is needed ***/ /*** ==> returns the actual ROLL value of the camera ***/ /**************************************************************************************/ float CD3dcam::GetRoll() const { return mRoll; } /**************************************************************************************/ /*** GET LOOK CONST ***/ /*** ==> usage: to retrieve current camera 'look' vector ***/ /*** ==> returns the 'look' of camera as XMFLOAT3 ***/ /**************************************************************************************/ XMFLOAT3 CD3dcam::GetLook() const { XMFLOAT3 mLookVector = XMFLOAT3(mMatView._13, mMatView._23, mMatView._33); return mLookVector; } /**************************************************************************************/ /*** POINT IN FRUSTUM CONST ***/ /*** ==> usage: before rendering a object or subobject, during frame rendering ***/ /*** ==> checks a point with worlspace pos against the current frustum ***/ /**************************************************************************************/ int CD3dcam::PointInFrustum(const XMFLOAT3 &pPosition) const { for(int i=0;i<6;++i) { XMVECTOR xmPlane = XMLoadFloat4(&mFrustumPlane[i]); XMVECTOR xmPos = XMLoadFloat3(&pPosition); XMVECTOR dot = XMPlaneDotCoord(xmPlane, xmPos); if(XMVectorGetX(dot) < 0) { return OUTSIDE; } } return INSIDE; } /**************************************************************************************/ /*** SPHERE IN FRUSTUM CONST ***/ /*** ==> usage: before rendering a object or subobject, during frame rendering ***/ /*** ==> checks a sphere with worldspace pos and radius against the current frustum ***/ /**************************************************************************************/ int CD3dcam::SphereInFrustum(const SPHERE &pSphere) const { bool intersect = false; for(int i=0;i<6;++i) { XMVECTOR xmPlane = XMLoadFloat4(&mFrustumPlane[i]); XMVECTOR xmPos = XMLoadFloat3(&pSphere.WorldCenter); XMVECTOR dot = XMPlaneDotCoord(xmPlane, xmPos); float dist = XMVectorGetX(dot); if(dist < -pSphere.Radius) { return OUTSIDE; } if(fabs(dist) < pSphere.Radius) intersect = true; } if(intersect) return INTERSECT; return INSIDE; } /**************************************************************************************/ /*** SPHERE IN FRUSTUM (2) CONST ***/ /*** ==> usage: before rendering a object or subobject, during frame rendering ***/ /*** ==> checks a sphere with worldspace pos and radius against the current frustum ***/ /**************************************************************************************/ int CD3dcam::SphereInFrustum(const XMFLOAT3 &pCenter, const float &pRadius) const { SPHERE tempSphere; tempSphere.Radius = pRadius; tempSphere.WorldCenter = pCenter; return SphereInFrustum(tempSphere); } /**************************************************************************************/ /*** OBB IN FRUSTUM CONST ***/ /*** ==> usage: before rendering, in scenegraph ***/ /*** ==> checks a OBB against the current frustum planes ***/ /**************************************************************************************/ int CD3dcam::OBBInFrustum(const OBB &pOBB) const { int _result = 99; float d, s; for(int i=0;i<6;++i) { XMVECTOR xmPlane = XMLoadFloat4(&mFrustumPlane[i]); XMVECTOR xmPos = { pOBB.Center.x, pOBB.Center.y, pOBB.Center.z }; XMVECTOR dot = XMPlaneDotCoord(xmPlane, xmPos); d = XMVectorGetX(dot); XMVECTOR planeXYZ = { mFrustumPlane[i].x, mFrustumPlane[i].y, mFrustumPlane[i].z }; XMVECTOR xmXHalf = { pOBB.XHalfExtent.x, pOBB.XHalfExtent.y, pOBB.XHalfExtent.z }; XMVECTOR xmYHalf = { pOBB.YHalfExtent.x, pOBB.YHalfExtent.y, pOBB.YHalfExtent.z }; XMVECTOR xmZHalf = { pOBB.ZHalfExtent.x, pOBB.ZHalfExtent.y, pOBB.ZHalfExtent.z }; s = fabs(XMVectorGetX(XMVector3Dot(planeXYZ, xmXHalf))) + fabs(XMVectorGetX(XMVector3Dot(planeXYZ, xmYHalf))) + fabs(XMVectorGetX(XMVector3Dot(planeXYZ, xmZHalf))); if(d < -s) return OUTSIDE; if(d+ -s < 0) _result = INTERSECT; } if(_result == INTERSECT) return INTERSECT; else return INSIDE; return INSIDE; } /**************************************************************************************/ /*** AABB IN FRUSTUM CONST ***/ /*** ==> usage: before rendering, in scenegraph ***/ /*** ==> checks a AABB in worldspace against frustum planes, using pos/neg vertex ***/ /**************************************************************************************/ int CD3dcam::AABBInFrustum(const Crealysm_dxmath::AABBWORLD &pAABBworld) const { XMFLOAT3 _pvtx, _nvtx; bool intersect = false; float dist; XMFLOAT3 center = pAABBworld.Center; XMFLOAT3 extents = pAABBworld.Extents(); for(int i=0;i<6;++i) { // find the nearest and farthest point along normal direction _pvtx.x = center.x + (extents.x / 2.0f) * mFrustumPlaneSign[i].x; _pvtx.y = center.y + (extents.y / 2.0f) * mFrustumPlaneSign[i].y; _pvtx.z = center.z + (extents.z / 2.0f) * mFrustumPlaneSign[i].z; _nvtx.x = center.x - (extents.x / 2.0f) * mFrustumPlaneSign[i].x; _nvtx.y = center.y - (extents.y / 2.0f) * mFrustumPlaneSign[i].y; _nvtx.z = center.z - (extents.z / 2.0f) * mFrustumPlaneSign[i].z; // check positive vertex; further along the normal's direction XMVECTOR xmPvtx = { _pvtx.x, _pvtx.y, _pvtx.z }; XMVECTOR xmPlane = XMLoadFloat4(&mFrustumPlane[i]); XMVECTOR dot = XMPlaneDotCoord(xmPlane, xmPvtx); dist = XMVectorGetX(dot); if(dist < 0) return OUTSIDE; // wrong side of plane, completely outside // check negative vertex; less far along the normal's direction XMVECTOR xmNvtx = { _nvtx.x, _nvtx.y, _nvtx.z }; dot = XMPlaneDotCoord(xmPlane, xmNvtx); dist = XMVectorGetX(dot); if(dist < 0) intersect = true; } if(intersect) return INTERSECT; return INSIDE; } /**************************************************************************************/ /*** BOX IN FRUSTUM - VARIANCES POSSIBLE ***/ /*** ==> checks an AABB against the current frustum planes ***/ /**************************************************************************************/ // OPTION1: make a boundingsphere radius based on half diagonal (min - max) // dot product between center of sphere and plane, compare with radius // RESULT: semi OK, not very accurate at closeup // ==================================================================================== /* bool CD3dcam::BoxInFrustum(BOUNDINGBOX *pBoundingBox) { float m, n; for(int i=0;i<6;++i) { m = (pBoundingBox->center.x * mFrustumPlane[i].a) + (pBoundingBox->center.y * mFrustumPlane[i].b) + (pBoundingBox->center.z * mFrustumPlane[i].c) + mFrustumPlane[i].d; xxxxVECTOR3 dx = pBoundingBox->max - pBoundingBox->center; n = (dx.x * fabs(mFrustumPlane[i].a)) + (dx.y * fabs(mFrustumPlane[i].b)) + (dx.z * fabs(mFrustumPlane[i].c)); if(m + n < 0) return false; if(m - n < 0) return true; } return true; } */ /**************************************************************************************/ // OPTION2: check all 8 points of the AABB against the 6 planes // RESULT: very accurate, alhtough 8 checks needed each time // ============================================================================================== /* bool CD3dcam::BoxInFrustum(BOUNDINGBOX *pBoundingBox) { int iTotalIn = 0; for(int i=0;i<6;++i) { int iInCount = 8; int iPtIn = 1; for(int bc=0;bc<8;++bc) { if(D3DXPlaneDotCoord(&mFrustumPlane[i], &pBoundingBox->boxArray[bc]) < 0) { iPtIn = 0; iInCount--; } } if(iInCount == 0) return false; iTotalIn += iPtIn; } if(iTotalIn == 0) return false; else return true; } */ }