aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Samples/SampleBase/SampleCamera.cpp
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Samples/SampleBase/SampleCamera.cpp
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'PhysX_3.4/Samples/SampleBase/SampleCamera.cpp')
-rw-r--r--PhysX_3.4/Samples/SampleBase/SampleCamera.cpp481
1 files changed, 481 insertions, 0 deletions
diff --git a/PhysX_3.4/Samples/SampleBase/SampleCamera.cpp b/PhysX_3.4/Samples/SampleBase/SampleCamera.cpp
new file mode 100644
index 00000000..c86d55dd
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleBase/SampleCamera.cpp
@@ -0,0 +1,481 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#include "SampleCamera.h"
+#include "SampleUtils.h"
+#include "RenderPhysX3Debug.h"
+#include "RendererColor.h"
+
+using namespace SampleRenderer;
+
+// PT: the base camera code should be the same for all cameras, regardless of how
+// the camera is controlled. For example this should deal with VFC, etc.
+
+Camera::Camera() :
+ mProjMatrix (degtorad(45.0f), 1.0f, 1.0f, 100.0f),
+ mFOV (0.0f),
+ mNearPlane (0.0f),
+ mFarPlane (0.0f),
+ mDirtyProj (true),
+ mDirtyView (true)
+{
+ mViewMatrix = PxTransform(PxIdentity);
+ mPos = PxVec3(0);
+ mRot = PxVec3(0);
+
+ mDrawDebugData = false;
+ mFreezeFrustum = false;
+ mPerformVFC = true;
+}
+
+Camera::~Camera()
+{
+}
+
+// PT: TODO: copied from SampleApplication. Refactor.
+static PxMat33 EulerToMat33(const PxVec3 &e)
+{
+ float c1 = cosf(e.z);
+ float s1 = sinf(e.z);
+ float c2 = cosf(e.y);
+ float s2 = sinf(e.y);
+ float c3 = cosf(e.x);
+ float s3 = sinf(e.x);
+ PxMat33 m(PxVec3(c1*c2, -s1*c2, s2),
+ PxVec3((s1*c3)+(c1*s2*s3), (c1*c3)-(s1*s2*s3),-c2*s3),
+ PxVec3((s1*s3)-(c1*s2*c3), (c1*s3)+(s1*s2*c3), c2*c3));
+
+ return m;
+}
+
+void Camera::updateInternals()
+{
+ if(mDirtyProj)
+ {
+ mDirtyProj = false;
+ mProjMatrix = RendererProjection(degtorad(mFOV), mViewport.computeRatio(), mNearPlane, mFarPlane);
+ }
+ if(mDirtyView)
+ {
+ mDirtyView = false;
+
+ mViewMatrix.q = PxQuat(EulerToMat33(mRot));
+ mViewMatrix.p = mPos;
+ }
+}
+
+PxVec3 Camera::getViewDir() const
+{
+ const PxTransform& camPose = getViewMatrix();
+ PxVec3 forward = PxMat33(camPose.q)[2];
+ return -forward;
+}
+
+void Camera::lookAt(const PxVec3& position, const PxVec3& target)
+{
+ PxVec3 dir, right, up;
+ Ps::computeBasis(position, target, dir, right, up);
+
+ PxTransform view;
+ view.p = position;
+ view.q = PxQuat(PxMat33(-right, up, -dir));
+ setView(view);
+}
+
+
+ enum FrustumPlaneIndex
+ {
+ FRUSTUM_PLANE_LEFT = 0, //!< Left clipping plane
+ FRUSTUM_PLANE_RIGHT = 1, //!< Right clipping plane
+ FRUSTUM_PLANE_TOP = 2, //!< Top clipping plane
+ FRUSTUM_PLANE_BOTTOM = 3, //!< Bottom clipping plane
+ FRUSTUM_PLANE_NEAR = 4, //!< Near clipping plane
+ FRUSTUM_PLANE_FAR = 5, //!< Far clipping plane (must be last for infinite far clip)
+
+ FRUSTUM_PLANE_FORCE_DWORD = 0x7fffffff
+ };
+
+static PxMat44 convertViewMatrix(const PxTransform& eye)
+{
+ PxTransform viewMatrix = eye.getInverse();
+ PxMat44 mat44 = PxMat44(viewMatrix).getTranspose();
+
+ float m[16];
+ memcpy(m, mat44.front(), sizeof m);
+
+ PxMat44 view44;
+ view44.column0.x = m[0];
+ view44.column0.y = m[1];
+ view44.column0.z = m[2];
+ view44.column0.w = m[3];
+ view44.column1.x = m[4];
+ view44.column1.y = m[5];
+ view44.column1.z = m[6];
+ view44.column1.w = m[7];
+ view44.column2.x = m[8];
+ view44.column2.y = m[9];
+ view44.column2.z = m[10];
+ view44.column2.w = m[11];
+ view44.column3.x = m[12];
+ view44.column3.y = m[13];
+ view44.column3.z = m[14];
+ view44.column3.w = m[15];
+
+PxMat44 tmpmat = view44.getTranspose(); view44 = tmpmat;
+
+ return view44;
+}
+
+static PxMat44 convertProjMatrix(const RendererProjection& proj)
+{
+ float renderProjMatrix[16];
+ proj.getColumnMajor44(renderProjMatrix);
+
+ PxMat44 proj44;
+ proj44.column0.x = renderProjMatrix[0];
+ proj44.column0.y = renderProjMatrix[1];
+ proj44.column0.z = renderProjMatrix[2];
+ proj44.column0.w = renderProjMatrix[3];
+ proj44.column1.x = renderProjMatrix[4];
+ proj44.column1.y = renderProjMatrix[5];
+ proj44.column1.z = renderProjMatrix[6];
+ proj44.column1.w = renderProjMatrix[7];
+ proj44.column2.x = renderProjMatrix[8];
+ proj44.column2.y = renderProjMatrix[9];
+ proj44.column2.z = renderProjMatrix[10];
+ proj44.column2.w = renderProjMatrix[11];
+ proj44.column3.x = renderProjMatrix[12];
+ proj44.column3.y = renderProjMatrix[13];
+ proj44.column3.z = renderProjMatrix[14];
+ proj44.column3.w = renderProjMatrix[15];
+
+//PxMat44 tmpmat = proj44.getTranspose(); proj44 = tmpmat;
+
+ return proj44;
+}
+
+void Camera::BuildFrustum()
+{
+ if(mFreezeFrustum)
+ return;
+
+ // PT: a better way is to extract the planes from the view-proj matrix but it has some subtle differences with D3D/GL.
+ // Building the frustum explicitly is just easier here (although not as efficient)
+
+ const PxReal ratio = mViewport.computeRatio();
+
+ const PxReal Tan = tanf(degtorad(0.5f * mFOV)) / ratio;
+
+ const PxReal nearCoeff = mNearPlane * Tan;
+ const PxReal farCoeff = mFarPlane * Tan;
+
+ const PxReal rightCoeff = ratio;
+ const PxReal upCoeff = 1.0f;
+
+ const PxTransform& view = getViewMatrix();
+ PxMat33 mat33(view.q);
+ PxVec3 right = mat33[0];
+ PxVec3 up = mat33[1];
+ PxVec3 forward =-mat33[2];
+
+ mFrustum[0] = mPos + forward*mNearPlane - right*nearCoeff*rightCoeff + up*nearCoeff*upCoeff;
+ mFrustum[1] = mPos + forward*mNearPlane - right*nearCoeff*rightCoeff - up*nearCoeff*upCoeff;
+ mFrustum[2] = mPos + forward*mNearPlane + right*nearCoeff*rightCoeff - up*nearCoeff*upCoeff;
+ mFrustum[3] = mPos + forward*mNearPlane + right*nearCoeff*rightCoeff + up*nearCoeff*upCoeff;
+
+ mFrustum[4] = mPos + forward*mFarPlane - right*farCoeff*rightCoeff + up*farCoeff*upCoeff;
+ mFrustum[5] = mPos + forward*mFarPlane - right*farCoeff*rightCoeff - up*farCoeff*upCoeff;
+ mFrustum[6] = mPos + forward*mFarPlane + right*farCoeff*rightCoeff - up*farCoeff*upCoeff;
+ mFrustum[7] = mPos + forward*mFarPlane + right*farCoeff*rightCoeff + up*farCoeff*upCoeff;
+
+ if(1)
+ {
+ mPlanes[0] = PxPlane(mFrustum[4], mFrustum[1], mFrustum[5]);
+ mPlanes[1] = PxPlane(mFrustum[6], mFrustum[3], mFrustum[7]);
+ mPlanes[2] = PxPlane(mFrustum[4], mFrustum[7], mFrustum[3]);
+ mPlanes[3] = PxPlane(mFrustum[1], mFrustum[6], mFrustum[5]);
+ mPlanes[4] = PxPlane(mFrustum[0], mFrustum[2], mFrustum[1]);
+ mPlanes[5] = PxPlane(mFrustum[5], mFrustum[7], mFrustum[4]);
+
+ {
+ for(int i=0;i<6;i++)
+ {
+ mPlanes[i].n = -mPlanes[i].n;
+ mPlanes[i].d = -mPlanes[i].d;
+ }
+ }
+ }
+
+ if(0)
+ {
+ //
+ const PxVec3 axisX(1.0f, 0.0f, 0.0f);
+ const PxVec3 axisY(0.0f, 1.0f, 0.0f);
+ const PxVec3 axisZ(0.0f, 0.0f, 1.0f);
+
+ PxQuat RotX(degtorad(0.5f * mFOV), axisX);
+ PxQuat RotY(degtorad(0.5f * mFOV), axisY);
+ PxQuat RotZ(degtorad(0.5f * mFOV), axisZ);
+
+ PxVec3 tmp1 = RotY.rotate(-axisX);
+ PxVec3 tmp11 = view.q.rotate(tmp1); // Plane0
+ mPlanes[0].n = tmp11;
+ mPlanes[0].d = - mPos.dot(mPlanes[0].n);
+ //
+
+ RotY = PxQuat(-degtorad(0.5f * mFOV), axisY);
+
+ PxVec3 tmpy = RotY.rotate(axisX);
+ PxVec3 tmpyy = view.q.rotate(tmpy); // Plane1
+ mPlanes[1].n = tmpyy;
+ mPlanes[1].d = - mPos.dot(mPlanes[1].n);
+
+ //
+
+ RotX = PxQuat(degtorad(0.5f * mFOV)/ratio, axisX);
+ PxVec3 tmpx = RotX.rotate(axisY);
+ PxVec3 tmpxx = view.q.rotate(tmpx); // Plane2?
+ mPlanes[2].n = tmpxx;
+ mPlanes[2].d = - mPos.dot(mPlanes[2].n);
+
+ //
+
+ RotX = PxQuat(-degtorad(0.5f * mFOV)/ratio, axisX);
+ tmpx = RotX.rotate(axisY);
+ tmpxx = view.q.rotate(tmpx); // -Plane3?
+ mPlanes[3].n = -tmpxx;
+ mPlanes[3].d = - mPos.dot(mPlanes[3].n);
+
+ //
+
+ mPlanes[4].n = -forward;
+ mPlanes[4].d = - (mPos.dot(mPlanes[4].n) + forward.dot(mPlanes[4].n)*mNearPlane);
+
+ mPlanes[5].n = forward;
+ mPlanes[5].d = - (mPos.dot(mPlanes[5].n) + forward.dot(mPlanes[5].n)*mFarPlane);
+ }
+
+
+ if(0)
+ {
+ PxMat44 proj44 = convertProjMatrix(mProjMatrix);
+ PxMat44 view44 = convertViewMatrix(view);
+// PxMat44 combo44 = view44 * proj44;
+ PxMat44 combo44 = proj44 * view44;
+
+ PxReal combo[4][4];
+ PxReal* dst = &combo[0][0];
+ memcpy(dst, &combo44, sizeof(PxReal)*16);
+
+ // D3D:
+ // -w' < x' < w'
+ // -w' < y' < w'
+ // 0 < z' < w'
+ //
+ // GL:
+ // -w' < x' < w'
+ // -w' < y' < w'
+ // -w' < z' < w'
+
+ // Left clipping plane
+ mPlanes[FRUSTUM_PLANE_LEFT].n.x = -(combo[0][3] + combo[0][0]);
+ mPlanes[FRUSTUM_PLANE_LEFT].n.y = -(combo[1][3] + combo[1][0]);
+ mPlanes[FRUSTUM_PLANE_LEFT].n.z = -(combo[2][3] + combo[2][0]);
+ mPlanes[FRUSTUM_PLANE_LEFT].d = -(combo[3][3] + combo[3][0]);
+
+ // Right clipping plane
+ mPlanes[FRUSTUM_PLANE_RIGHT].n.x = -(combo[0][3] - combo[0][0]);
+ mPlanes[FRUSTUM_PLANE_RIGHT].n.y = -(combo[1][3] - combo[1][0]);
+ mPlanes[FRUSTUM_PLANE_RIGHT].n.z = -(combo[2][3] - combo[2][0]);
+ mPlanes[FRUSTUM_PLANE_RIGHT].d = -(combo[3][3] - combo[3][0]);
+
+ // Top clipping plane
+ mPlanes[FRUSTUM_PLANE_TOP].n.x = -(combo[0][3] - combo[0][1]);
+ mPlanes[FRUSTUM_PLANE_TOP].n.y = -(combo[1][3] - combo[1][1]);
+ mPlanes[FRUSTUM_PLANE_TOP].n.z = -(combo[2][3] - combo[2][1]);
+ mPlanes[FRUSTUM_PLANE_TOP].d = -(combo[3][3] - combo[3][1]);
+
+ // Bottom clipping plane
+ mPlanes[FRUSTUM_PLANE_BOTTOM].n.x = -(combo[0][3] + combo[0][1]);
+ mPlanes[FRUSTUM_PLANE_BOTTOM].n.y = -(combo[1][3] + combo[1][1]);
+ mPlanes[FRUSTUM_PLANE_BOTTOM].n.z = -(combo[2][3] + combo[2][1]);
+ mPlanes[FRUSTUM_PLANE_BOTTOM].d = -(combo[3][3] + combo[3][1]);
+
+ // Near clipping plane
+ if(1)
+ {
+ // OpenGL path
+ mPlanes[FRUSTUM_PLANE_NEAR].n.x = -(combo[0][3] + combo[0][2]);
+ mPlanes[FRUSTUM_PLANE_NEAR].n.y = -(combo[1][3] + combo[1][2]);
+ mPlanes[FRUSTUM_PLANE_NEAR].n.z = -(combo[2][3] + combo[2][2]);
+ mPlanes[FRUSTUM_PLANE_NEAR].d = -(combo[3][3] + combo[3][2]);
+ }
+ else
+ {
+ // D3D path
+ mPlanes[FRUSTUM_PLANE_NEAR].n.x = - combo[0][2];
+ mPlanes[FRUSTUM_PLANE_NEAR].n.y = - combo[1][2];
+ mPlanes[FRUSTUM_PLANE_NEAR].n.z = - combo[2][2];
+ mPlanes[FRUSTUM_PLANE_NEAR].d = - combo[3][2];
+ }
+
+ // Far clipping plane (must be last for infinite far clip)
+ mPlanes[FRUSTUM_PLANE_FAR].n.x = -(combo[0][3] - combo[0][2]);
+ mPlanes[FRUSTUM_PLANE_FAR].n.y = -(combo[1][3] - combo[1][2]);
+ mPlanes[FRUSTUM_PLANE_FAR].n.z = -(combo[2][3] - combo[2][2]);
+ mPlanes[FRUSTUM_PLANE_FAR].d = -(combo[3][3] - combo[3][2]);
+
+ // Normalize if needed
+ for(PxU32 i=0;i<6;i++)
+ {
+// mPlanes[i].normalize();
+ mPlanes[i].n.normalize();
+// mPlanes[i].normal = -mPlanes[i].normal;
+// mPlanes[i].d = -mPlanes[i].d;
+ mPlanes[i].d *= 0.5f;
+ }
+ }
+}
+
+ // Following code from Umbra/dPVS.
+
+ //------------------------------------------------------------------------
+ //
+ // Function: DPVS::intersectAABBFrustum()
+ //
+ // Description: Determines whether an AABB intersects a frustum
+ //
+ // Parameters: a = reference to AABB (defined by minimum & maximum vectors)
+ // p = array of pre-normalized clipping planes
+ // outClipMask = output clip mask (if function returns 'true')
+ // inClipMask = input clip mask (indicates which planes are active)
+ //
+ // Returns: true if AABB intersects the frustum, false otherwise
+ //
+ // Intersection of AABB and a frustum. The frustum may
+ // contain 0-32 planes (active planes are defined by inClipMask).
+ // If AABB intersects the frustum, an output clip mask is returned
+ // as well (indicating which planes are crossed by the AABB). This
+ // information can be used to optimize testing of child nodes or
+ // objects inside the nodes (pass value as 'inClipMask' next time).
+ //
+ // This is a variant of the classic "fast" AABB/frustum
+ // intersection tester. AABBs that are not culled away by any single
+ // plane are classified as "intersecting" even though the AABB may
+ // actually be outside the convex volume formed by the planes.
+ //------------------------------------------------------------------------
+
+static PX_FORCE_INLINE bool planesAABBOverlap(const PxBounds3& a, const PxPlane* p, PxU32& out_clip_mask, PxU32 in_clip_mask)
+ {
+ //------------------------------------------------------------------------
+ // Convert the AABB from (minimum,maximum) form into (center,half-diagonal).
+ // Note that we could get rid of these six subtractions and three
+ // multiplications if the AABB was originally expressed in (center,
+ // half-diagonal) form.
+ //------------------------------------------------------------------------
+
+ PxVec3 m = a.getCenter(); // get center of AABB ((minimum+maximum)*0.5f)
+ PxVec3 d = a.maximum; d-=m; // get positive half-diagonal (maximum - center)
+
+ //------------------------------------------------------------------------
+ // Evaluate through all active frustum planes. We determine the relation
+ // between the AABB and a plane by using the concept of "near" and "far"
+ // vertices originally described by Zhang (and later by Moeller). Our
+ // variant here uses 3 fabs ops, 6 muls, 7 adds and two floating point
+ // comparisons per plane. The routine early-exits if the AABB is found
+ // to be outside any of the planes. The loop also constructs a new output
+ // clip mask. Most FPUs have a native single-cycle fabsf() operation.
+ //------------------------------------------------------------------------
+
+ PxU32 Mask = 1; // current mask index (1,2,4,8,..)
+ PxU32 TmpOutClipMask = 0; // initialize output clip mask into empty.
+
+ while(Mask<=in_clip_mask) // keep looping while we have active planes left...
+ {
+ if(in_clip_mask & Mask) // if clip plane is active, process it..
+ {
+ const float NP = d.x*PxAbs(p->n.x) + d.y*PxAbs(p->n.y) + d.z*PxAbs(p->n.z);
+ const float MP = m.x*p->n.x + m.y*p->n.y + m.z*p->n.z + p->d;
+
+ if(NP < MP) // near vertex behind the clip plane...
+ return false; // .. so there is no intersection..
+ if((-NP) < MP) // near and far vertices on different sides of plane..
+ TmpOutClipMask |= Mask; // .. so update the clip mask...
+ }
+ Mask+=Mask; // mk = (1<<plane)
+ p++; // advance to next plane
+ }
+
+ out_clip_mask = TmpOutClipMask; // copy output value (temp used to resolve aliasing!)
+ return true; // indicate that AABB intersects frustum
+ }
+
+PlaneAABBCode Camera::cull(const PxBounds3& aabb) const
+{
+ const PxU32 nbFrustumPlanes = 6; // PT: can sometimes be 5 with infinite far clip plane
+ const PxU32 frustumPlanesMask = (1<<nbFrustumPlanes)-1;
+
+ PxU32 outClipMask;
+ if(!planesAABBOverlap(aabb, mPlanes, outClipMask, frustumPlanesMask))
+ return PLANEAABB_EXCLUSION;
+
+ if(outClipMask)
+ return PLANEAABB_INTERSECT;
+
+ return PLANEAABB_INCLUSION;
+}
+
+void Camera::drawDebug(RenderPhysX3Debug* debug)
+{
+ if(mDrawDebugData)
+ {
+/* for(PxU32 i=0;i<8;i++)
+ {
+ debug->addLine(mFrustum[i], mFrustum[i]+PxVec3(1,0,0), RendererColor(255,0,0));
+ debug->addLine(mFrustum[i], mFrustum[i]+PxVec3(0,1,0), RendererColor(0, 255,0));
+ debug->addLine(mFrustum[i], mFrustum[i]+PxVec3(0,0,1), RendererColor(0, 0, 255));
+ }*/
+
+ const RendererColor lineColor(255, 255, 0);
+ debug->addLine(mFrustum[0], mFrustum[1], lineColor);
+ debug->addLine(mFrustum[1], mFrustum[2], lineColor);
+ debug->addLine(mFrustum[2], mFrustum[3], lineColor);
+ debug->addLine(mFrustum[3], mFrustum[0], lineColor);
+
+ debug->addLine(mFrustum[4], mFrustum[5], lineColor);
+ debug->addLine(mFrustum[5], mFrustum[6], lineColor);
+ debug->addLine(mFrustum[6], mFrustum[7], lineColor);
+ debug->addLine(mFrustum[7], mFrustum[4], lineColor);
+
+ debug->addLine(mFrustum[0], mFrustum[4], lineColor);
+ debug->addLine(mFrustum[3], mFrustum[7], lineColor);
+ debug->addLine(mFrustum[1], mFrustum[5], lineColor);
+ debug->addLine(mFrustum[6], mFrustum[2], lineColor);
+ }
+}