diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /APEX_1.4/shared/general/RenderDebug/src/ProcessRenderDebug.cpp | |
| download | physx-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 'APEX_1.4/shared/general/RenderDebug/src/ProcessRenderDebug.cpp')
| -rw-r--r-- | APEX_1.4/shared/general/RenderDebug/src/ProcessRenderDebug.cpp | 3342 |
1 files changed, 3342 insertions, 0 deletions
diff --git a/APEX_1.4/shared/general/RenderDebug/src/ProcessRenderDebug.cpp b/APEX_1.4/shared/general/RenderDebug/src/ProcessRenderDebug.cpp new file mode 100644 index 00000000..41814a44 --- /dev/null +++ b/APEX_1.4/shared/general/RenderDebug/src/ProcessRenderDebug.cpp @@ -0,0 +1,3342 @@ +// 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-2013 NVIDIA Corporation. All rights reserved. + +#include "ProcessRenderDebug.h" +#include "PsMemoryBuffer.h" +#include "PxBounds3.h" +#include "StreamIO.h" +#include "Hull2MeshEdges.h" + +namespace RENDER_DEBUG +{ + +static float degToRad(const float a) +{ + return static_cast<float>(0.01745329251994329547) * a; +} + +static physx::PxQuat slerp(const float t, const physx::PxQuat& left, const physx::PxQuat& right) +{ + const float quatEpsilon = (float(1.0e-8f)); + + float cosine = left.dot(right); + float sign = float(1); + if (cosine < 0) + { + cosine = -cosine; + sign = float(-1); + } + + float sine = float(1) - cosine*cosine; + + if(sine>=quatEpsilon*quatEpsilon) + { + sine = physx::PxSqrt(sine); + const float angle = physx::PxAtan2(sine, cosine); + const float i_sin_angle = float(1) / sine; + + const float leftw = physx::PxSin(angle*(float(1)-t)) * i_sin_angle; + const float rightw = physx::PxSin(angle * t) * i_sin_angle * sign; + + return left * leftw + right * rightw; + } + + return left; +} + + + physx::PxQuat NvShortestRotation(const physx::PxVec3& v0, const physx::PxVec3& v1) + { + const float d = v0.dot(v1); + const physx::PxVec3 cross = v0.cross(v1); + + physx::PxQuat q = d>-1 ? physx::PxQuat(cross.x, cross.y, cross.z, 1+d) + : physx::PxAbs(v0.x)<0.1f ? physx::PxQuat(0.0f, v0.z, -v0.y, 0.0f) : physx::PxQuat(v0.y, -v0.x, 0.0f, 0.0f); + + return q.getNormalized(); + } + + + + physx::PxMat44 invert(const physx::PxMat44 &m) + { + physx::PxMat44 inv; + +#define det3x3(a0, a1, a2, a3, a4, a5, a6, a7, a8) \ + (a0 * (a4*a8 - a7*a5) - a1 * (a3*a8 - a6*a5) + a2 * (a3*a7 - a6*a4)) + + inv.column0.x = det3x3(m.column1.y, m.column1.z, m.column1.w, m.column2.y, m.column2.z, m.column2.w, m.column3.y, m.column3.z, m.column3.w); + inv.column0.y = -det3x3(m.column0.y, m.column0.z, m.column0.w, m.column2.y, m.column2.z, m.column2.w, m.column3.y, m.column3.z, m.column3.w); + inv.column0.z = det3x3(m.column0.y, m.column0.z, m.column0.w, m.column1.y, m.column1.z, m.column1.w, m.column3.y, m.column3.z, m.column3.w); + inv.column0.w = -det3x3(m.column0.y, m.column0.z, m.column0.w, m.column1.y, m.column1.z, m.column1.w, m.column2.y, m.column2.z, m.column2.w); + + inv.column1.x = -det3x3(m.column1.x, m.column1.z, m.column1.w, m.column2.x, m.column2.z, m.column2.w, m.column3.x, m.column3.z, m.column3.w); + inv.column1.y = det3x3(m.column0.x, m.column0.z, m.column0.w, m.column2.x, m.column2.z, m.column2.w, m.column3.x, m.column3.z, m.column3.w); + inv.column1.z = -det3x3(m.column0.x, m.column0.z, m.column0.w, m.column1.x, m.column1.z, m.column1.w, m.column3.x, m.column3.z, m.column3.w); + inv.column1.w = det3x3(m.column0.x, m.column0.z, m.column0.w, m.column1.x, m.column1.z, m.column1.w, m.column2.x, m.column2.z, m.column2.w); + + inv.column2.x = det3x3(m.column1.x, m.column1.y, m.column1.w, m.column2.x, m.column2.y, m.column2.w, m.column3.x, m.column3.y, m.column3.w); + inv.column2.y = -det3x3(m.column0.x, m.column0.y, m.column0.w, m.column2.x, m.column2.y, m.column2.w, m.column3.x, m.column3.y, m.column3.w); + inv.column2.z = det3x3(m.column0.x, m.column0.y, m.column0.w, m.column1.x, m.column1.y, m.column1.w, m.column3.x, m.column3.y, m.column3.w); + inv.column2.w = -det3x3(m.column0.x, m.column0.y, m.column0.w, m.column1.x, m.column1.y, m.column1.w, m.column2.x, m.column2.y, m.column2.w); + + inv.column3.x = -det3x3(m.column1.x, m.column1.y, m.column1.z, m.column2.x, m.column2.y, m.column2.z, m.column3.x, m.column3.y, m.column3.z); + inv.column3.y = det3x3(m.column0.x, m.column0.y, m.column0.z, m.column2.x, m.column2.y, m.column2.z, m.column3.x, m.column3.y, m.column3.z); + inv.column3.z = -det3x3(m.column0.x, m.column0.y, m.column0.z, m.column1.x, m.column1.y, m.column1.z, m.column3.x, m.column3.y, m.column3.z); + inv.column3.w = det3x3(m.column0.x, m.column0.y, m.column0.z, m.column1.x, m.column1.y, m.column1.z, m.column2.x, m.column2.y, m.column2.z); + +#undef det3x3 + + float det = m.column0.x*inv.column0.x + m.column1.x*inv.column0.y + m.column2.x*inv.column0.z + m.column3.x*inv.column0.w; + PX_ASSERT(det!=0); + if(!det) det = 1.0f; + float invDet = 1.0f / det; + + inv.column0 *= invDet; + inv.column1 *= invDet; + inv.column2 *= invDet; + inv.column3 *= invDet; + + return inv; + } + + +class ProcessRenderDebugHelper +{ +public: + virtual void indirectDebugLine(const physx::PxVec3 &p1,const physx::PxVec3 &p2) = 0; +protected: + virtual ~ProcessRenderDebugHelper(void) {} +}; + +const physx::PxVec3 debug_point[6] = +{ + physx::PxVec3(-1.0f, 0.0f, 0.0f), physx::PxVec3(1.0f, 0.0f, 0.0f), + physx::PxVec3(0.0f,-1.0f, 0.0f), physx::PxVec3(0.0f, 1.0f, 0.0f), + physx::PxVec3(0.0f, 0.0f,-1.0f), physx::PxVec3(0.0f, 0.0f, 1.0f) +}; + +// simple sphere, uses subdivision to enhance... +static physx::PxVec3 simpleSpherePosition[6] = +{ + physx::PxVec3( 1.0f, 0.0f, 0.0f), + physx::PxVec3(-1.0f, 0.0f, 0.0f), + physx::PxVec3( 0.0f, 1.0f, 0.0f), + physx::PxVec3( 0.0f,-1.0f, 0.0f), + physx::PxVec3( 0.0f, 0.0f, 1.0f), + physx::PxVec3( 0.0f, 0.0f,-1.0f), +}; + +static uint32_t simpleSphereIndices[8*3] = +{ + 0, 2, 4, + 1, 4, 2, + 0, 5, 2, + 1, 2, 5, + + 0, 4, 3, + 1, 3, 4, + 0, 3, 5, + 1, 5, 3, +}; + + +const float FM_PI = 3.1415926535897932384626433832795028841971693993751f; +const float FM_DEG_TO_RAD = ((2.0f * FM_PI) / 360.0f); +//const float FM_RAD_TO_DEG = (360.0f / (2.0f * FM_PI)); + +PX_INLINE void pxVec3FromArray(physx::PxVec3 &p,const float *pos) +{ + p.x = pos[0]; + p.y = pos[1]; + p.z = pos[2]; +} + +// quat to rotate v0 t0 v1 +static PX_INLINE physx::PxQuat rotationArc(const physx::PxVec3& v0, const physx::PxVec3& v1) +{ + const physx::PxVec3 cross = v0.cross(v1); + const float d = v0.dot(v1); + if(d<=-0.99999f) + return (physx::PxAbs(v0.x)<0.1f ? physx::PxQuat(0.0f, v0.z, -v0.y, 0.0f) : physx::PxQuat(v0.y, -v0.x, 0.0, 0.0)).getNormalized(); + + const float s = physx::PxSqrt((1+d)*2), r = 1/s; + + return physx::PxQuat(cross.x*r, cross.y*r, cross.z*r, s*0.5f).getNormalized(); +} + +static PX_INLINE void rotationArc(const physx::PxVec3 &v0,const physx::PxVec3 &v1,physx::PxQuat &quat) +{ + quat = rotationArc(v0,v1); +} + +/*const float debug_sphere[32*9] = +{ + 0.0000f, 0.0000f, 1.0000f, 0.7071f, 0.0000f, 0.7071f, 0.0000f, 0.7071f, 0.7071f, + 0.7071f, 0.0000f, 0.7071f, 1.0000f, 0.0000f, 0.0000f, 0.7071f, 0.7071f, 0.0000f, + 0.7071f, 0.0000f, 0.7071f, 0.7071f, 0.7071f, 0.0000f, 0.0000f, 0.7071f, 0.7071f, + 0.0000f, 0.7071f, 0.7071f, 0.7071f, 0.7071f, 0.0000f, 0.0000f, 1.0000f, 0.0000f, + 0.0000f, 0.0000f, 1.0000f, 0.0000f, 0.7071f, 0.7071f, -0.7071f, 0.0000f, 0.7071f, + 0.0000f, 0.7071f, 0.7071f, 0.0000f, 1.0000f, 0.0000f, -0.7071f, 0.7071f, 0.0000f, + 0.0000f, 0.7071f, 0.7071f, -0.7071f, 0.7071f, 0.0000f, -0.7071f, 0.0000f, 0.7071f, + -0.7071f, 0.0000f, 0.7071f, -0.7071f, 0.7071f, 0.0000f, -1.0000f, 0.0000f, 0.0000f, + 0.0000f, 0.0000f, 1.0000f, -0.7071f, 0.0000f, 0.7071f, 0.0000f, -0.7071f, 0.7071f, + -0.7071f, 0.0000f, 0.7071f, -1.0000f, 0.0000f, 0.0000f, -0.7071f, -0.7071f, 0.0000f, + -0.7071f, 0.0000f, 0.7071f, -0.7071f, -0.7071f, 0.0000f, 0.0000f, -0.7071f, 0.7071f, + 0.0000f, -0.7071f, 0.7071f, -0.7071f, -0.7071f, 0.0000f, 0.0000f, -1.0000f, 0.0000f, + 0.0000f, 0.0000f, 1.0000f, 0.0000f, -0.7071f, 0.7071f, 0.7071f, 0.0000f, 0.7071f, + 0.0000f, -0.7071f, 0.7071f, 0.0000f, -1.0000f, 0.0000f, 0.7071f, -0.7071f, 0.0000f, + 0.0000f, -0.7071f, 0.7071f, 0.7071f, -0.7071f, 0.0000f, 0.7071f, 0.0000f, 0.7071f, + 0.7071f, 0.0000f, 0.7071f, 0.7071f, -0.7071f, 0.0000f, 1.0000f, 0.0000f, 0.0000f, + 0.0000f, 0.0000f, -1.0000f, 0.0000f, 0.7071f, -0.7071f, 0.7071f, 0.0000f, -0.7071f, + 0.0000f, 0.7071f, -0.7071f, 0.0000f, 1.0000f, 0.0000f, 0.7071f, 0.7071f, 0.0000f, + 0.0000f, 0.7071f, -0.7071f, 0.7071f, 0.7071f, 0.0000f, 0.7071f, 0.0000f, -0.7071f, + 0.7071f, 0.0000f, -0.7071f, 0.7071f, 0.7071f, 0.0000f, 1.0000f, 0.0000f, 0.0000f, + 0.0000f, 0.0000f, -1.0000f, -0.7071f, 0.0000f, -0.7071f, 0.0000f, 0.7071f, -0.7071f, + -0.7071f, 0.0000f, -0.7071f, -1.0000f, 0.0000f, 0.0000f, -0.7071f, 0.7071f, 0.0000f, + -0.7071f, 0.0000f, -0.7071f, -0.7071f, 0.7071f, 0.0000f, 0.0000f, 0.7071f, -0.7071f, + 0.0000f, 0.7071f, -0.7071f, -0.7071f, 0.7071f, 0.0000f, 0.0000f, 1.0000f, 0.0000f, + 0.0000f, 0.0000f, -1.0000f, 0.0000f, -0.7071f, -0.7071f, -0.7071f, 0.0000f, -0.7071f, + 0.0000f, -0.7071f, -0.7071f, 0.0000f, -1.0000f, 0.0000f, -0.7071f, -0.7071f, 0.0000f, + 0.0000f, -0.7071f, -0.7071f, -0.7071f, -0.7071f, 0.0000f, -0.7071f, 0.0000f, -0.7071f, + -0.7071f, 0.0000f, -0.7071f, -0.7071f, -0.7071f, 0.0000f, -1.0000f, 0.0000f, 0.0000f, + 0.0000f, 0.0000f, -1.0000f, 0.7071f, 0.0000f, -0.7071f, 0.0000f, -0.7071f, -0.7071f, + 0.7071f, 0.0000f, -0.7071f, 1.0000f, 0.0000f, 0.0000f, 0.7071f, -0.7071f, 0.0000f, + 0.7071f, 0.0000f, -0.7071f, 0.7071f, -0.7071f, 0.0000f, 0.0000f, -0.7071f, -0.7071f, + 0.0000f, -0.7071f, -0.7071f, 0.7071f, -0.7071f, 0.0000f, 0.0000f, -1.0000f, 0.0000f, +};*/ + + + +// font info: +// +//Peter Holzmann, Octopus Enterprises +//USPS: 19611 La Mar Court, Cupertino, CA 95014 +//UUCP: {hplabs!hpdsd,pyramid}!octopus!pete +//Phone: 408/996-7746 +// +//This distribution is made possible through the collective encouragement +//of the Usenet Font Consortium, a mailing list that sprang to life to get +//this accomplished and that will now most likely disappear into the mists +//of time... Thanks are especially due to Jim Hurt, who provided the packed +//font data for the distribution, along with a lot of other help. +// +//This file describes the Hershey Fonts in general, along with a description of +//the other files in this distribution and a simple re-distribution restriction. +// +//USE RESTRICTION: +// This distribution of the Hershey Fonts may be used by anyone for +// any purpose, commercial or otherwise, providing that: +// 1. The following acknowledgements must be distributed with +// the font data: +// - The Hershey Fonts were originally created by Dr. +// A. V. Hershey while working at the U. S. +// National Bureau of Standards. +// - The format of the Font data in this distribution +// was originally created by +// James Hurt +// Cognition, Inc. +// 900 Technology Park Drive +// Billerica, MA 01821 +// (mit-eddie!ci-dandelion!hurt) +// 2. The font data in this distribution may be converted into +// any other format *EXCEPT* the format distributed by +// the U.S. NTIS (which organization holds the rights +// to the distribution and use of the font data in that +// particular format). Not that anybody would really +// *want* to use their format... each point is described +// in eight bytes as "xxx yyy:", where xxx and yyy are +// the coordinate values as ASCII numbers. + + +uint8_t g_font[6350] = { + 0x46,0x4F,0x4E,0x54,0x01,0x00,0x00,0x00,0x43,0x01,0x00,0x00,0x5E,0x00,0x00,0x00,0xC4,0x06,0x00,0x00,0x0A,0xD7,0x23,0x3C,0x3D,0x0A,0x57,0x3E,0x0A,0xD7,0x23,0x3C, + 0x28,0x5C,0x8F,0x3D,0x0A,0xD7,0x23,0x3C,0x08,0xD7,0xA3,0x3C,0x00,0x00,0x00,0x00,0x08,0xD7,0x23,0x3C,0x0A,0xD7,0x23,0x3C,0x00,0x00,0x00,0x00,0x0A,0xD7,0xA3,0x3C, + 0x08,0xD7,0x23,0x3C,0x00,0x00,0x00,0x00,0x3D,0x0A,0x57,0x3E,0x00,0x00,0x00,0x00,0x28,0x5C,0x0F,0x3E,0x0A,0xD7,0xA3,0x3D,0x3D,0x0A,0x57,0x3E,0x0A,0xD7,0xA3,0x3D, + 0x28,0x5C,0x0F,0x3E,0x0A,0xD7,0xA3,0x3D,0x00,0x00,0x80,0x3E,0x0C,0xD7,0x23,0x3C,0x29,0x5C,0x8F,0xBD,0x29,0x5C,0x0F,0x3E,0x00,0x00,0x80,0x3E,0x29,0x5C,0x8F,0x3D, + 0x29,0x5C,0x8F,0xBD,0x0C,0xD7,0x23,0x3C,0x8F,0xC2,0xF5,0x3D,0x9A,0x99,0x19,0x3E,0x8F,0xC2,0xF5,0x3D,0x00,0x00,0x00,0x00,0x8E,0xC2,0x75,0x3D,0x29,0x5C,0x0F,0x3E, + 0x8E,0xC2,0x75,0x3D,0xCD,0xCC,0x4C,0x3D,0x00,0x00,0x80,0x3E,0xCD,0xCC,0x4C,0x3D,0x0A,0xD7,0x23,0xBD,0xEC,0x51,0xB8,0x3D,0x00,0x00,0x80,0x3E,0xEC,0x51,0xB8,0x3D, + 0x0A,0xD7,0x23,0xBD,0x29,0x5C,0x0F,0x3E,0xEB,0x51,0x38,0x3E,0x8F,0xC2,0xF5,0x3D,0xCC,0xCC,0x4C,0x3E,0xEC,0x51,0xB8,0x3D,0x3D,0x0A,0x57,0x3E,0xCD,0xCC,0x4C,0x3D, + 0x3D,0x0A,0x57,0x3E,0x0C,0xD7,0xA3,0x3C,0xCC,0xCC,0x4C,0x3E,0x00,0x00,0x00,0x00,0xEB,0x51,0x38,0x3E,0x00,0x00,0x00,0x00,0x0A,0xD7,0x23,0x3E,0x0C,0xD7,0x23,0x3C, + 0x28,0x5C,0x0F,0x3E,0x0C,0xD7,0xA3,0x3C,0xB8,0x1E,0x05,0x3E,0x0A,0xD7,0x23,0x3D,0x8F,0xC2,0xF5,0x3D,0xCD,0xCC,0xCC,0x3D,0xCC,0xCC,0xCC,0x3D,0x8F,0xC2,0xF5,0x3D, + 0xEB,0x51,0xB8,0x3D,0xB8,0x1E,0x05,0x3E,0x0A,0xD7,0xA3,0x3D,0x29,0x5C,0x0F,0x3E,0x8E,0xC2,0xF5,0x3C,0x8F,0xC2,0xF5,0x3D,0x08,0xD7,0x23,0x3C,0xEC,0x51,0xB8,0x3D, + 0x00,0x00,0x00,0x00,0xCD,0xCC,0x4C,0x3D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8E,0xC2,0xF5,0x3C,0xEB,0x51,0x38,0x3E,0x3D,0x0A,0x57,0x3E,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x28,0x5C,0x8F,0x3D,0x5C,0x8F,0x42,0x3E,0x28,0x5C,0x8F,0x3D,0x7A,0x14,0x2E,0x3E,0x8E,0xC2,0x75,0x3D,0x99,0x99,0x19,0x3E,0x0A,0xD7,0x23,0x3D, + 0x28,0x5C,0x0F,0x3E,0x08,0xD7,0xA3,0x3C,0x28,0x5C,0x0F,0x3E,0x08,0xD7,0x23,0x3C,0xCC,0xCC,0x4C,0x3E,0x8E,0xC2,0xF5,0x3C,0x3D,0x0A,0x57,0x3E,0x28,0x5C,0x8F,0x3D, + 0xCC,0xCC,0x4C,0x3E,0xCC,0xCC,0xCC,0x3D,0x5C,0x8F,0x42,0x3E,0xB8,0x1E,0x05,0x3E,0x5C,0x8F,0x42,0x3E,0x0A,0xD7,0x23,0x3E,0xCC,0xCC,0x4C,0x3E,0x28,0x5C,0x0F,0x3E, + 0x28,0x5C,0x8F,0x3D,0x8F,0xC2,0xF5,0x3D,0x8E,0xC2,0x75,0x3D,0xAE,0x47,0xE1,0x3D,0x0A,0xD7,0x23,0x3D,0xAE,0x47,0xE1,0x3D,0x08,0xD7,0xA3,0x3C,0xB8,0x1E,0x05,0x3E, + 0x00,0x00,0x00,0x00,0x99,0x99,0x19,0x3E,0x00,0x00,0x00,0x00,0x7A,0x14,0x2E,0x3E,0x08,0xD7,0x23,0x3C,0xEB,0x51,0x38,0x3E,0x8E,0xC2,0xF5,0x3C,0xEB,0x51,0x38,0x3E, + 0xCC,0xCC,0x4C,0x3D,0x0A,0xD7,0x23,0x3E,0x28,0x5C,0x8F,0x3D,0xCC,0xCC,0x4C,0x3E,0x8F,0xC2,0xF5,0x3D,0xCC,0xCC,0x4C,0x3E,0xB8,0x1E,0x05,0x3E,0x5C,0x8F,0x42,0x3E, + 0x28,0x5C,0x0F,0x3E,0xEB,0x51,0x38,0x3E,0x28,0x5C,0x0F,0x3E,0x7A,0x14,0x2E,0x3E,0xB8,0x1E,0x05,0x3E,0x0A,0xD7,0x23,0x3E,0xAE,0x47,0xE1,0x3D,0x8E,0xC2,0xF5,0x3D, + 0x8E,0xC2,0xF5,0x3C,0xCC,0xCC,0xCC,0x3D,0x08,0xD7,0x23,0x3C,0x0A,0xD7,0xA3,0x3D,0x00,0x00,0x00,0x00,0x09,0xD7,0x23,0x3D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0A,0xD7,0x23,0x3D,0x08,0xD7,0x23,0x3C,0x0A,0xD7,0xA3,0x3D,0x08,0xD7,0xA3,0x3C,0xEB,0x51,0xB8,0x3D,0xEB,0x51,0xB8,0x3D,0xB8,0x1E,0x05,0x3E,0xCC,0xCC,0xCC,0x3D, + 0x28,0x5C,0x0F,0x3E,0xAD,0x47,0xE1,0x3D,0x0A,0xD7,0x23,0x3E,0xAD,0x47,0xE1,0x3D,0xEB,0x51,0x38,0x3E,0xCC,0xCC,0xCC,0x3D,0xCC,0xCC,0x4C,0x3E,0x8E,0xC2,0x75,0x3D, + 0xCC,0xCC,0x4C,0x3E,0xCC,0xCC,0x4C,0x3D,0xEB,0x51,0x38,0x3E,0xCC,0xCC,0x4C,0x3D,0x0A,0xD7,0x23,0x3E,0x8E,0xC2,0x75,0x3D,0xB8,0x1E,0x05,0x3E,0x0A,0xD7,0xA3,0x3D, + 0xCC,0xCC,0xCC,0x3D,0xB8,0x1E,0x05,0x3E,0x8E,0xC2,0xF5,0x3C,0x99,0x99,0x19,0x3E,0x08,0xD7,0x23,0x3C,0x7A,0x14,0x2E,0x3E,0x00,0x00,0x00,0x00,0x0A,0xD7,0x23,0x3C, + 0x5C,0x8F,0x42,0x3E,0x00,0x00,0x00,0x00,0xCC,0xCC,0x4C,0x3E,0x0A,0xD7,0xA3,0x3C,0xEB,0x51,0x38,0x3E,0x0A,0xD7,0x23,0x3C,0x0A,0xD7,0x23,0x3E,0x00,0x00,0x00,0x00, + 0x99,0x99,0x19,0x3E,0x29,0x5C,0x8F,0x3D,0x00,0x00,0x80,0x3E,0xCC,0xCC,0x4C,0x3D,0x1E,0x85,0x6B,0x3E,0x8F,0xC2,0xF5,0x3C,0xCC,0xCC,0x4C,0x3E,0x00,0x00,0x00,0x00, + 0xAE,0x47,0xE1,0x3D,0x00,0x00,0x00,0x00,0x28,0x5C,0x8F,0x3D,0x8F,0xC2,0xF5,0x3C,0x0C,0xD7,0xA3,0xBC,0xCC,0xCC,0x4C,0x3D,0xCE,0xCC,0x4C,0xBD,0x00,0x00,0x00,0x00, + 0x00,0x00,0x80,0x3E,0x0A,0xD7,0xA3,0x3C,0x1E,0x85,0x6B,0x3E,0x0A,0xD7,0x23,0x3D,0xCC,0xCC,0x4C,0x3E,0x8F,0xC2,0x75,0x3D,0x0A,0xD7,0x23,0x3E,0x29,0x5C,0x8F,0x3D, + 0xAE,0x47,0xE1,0x3D,0x29,0x5C,0x8F,0x3D,0x28,0x5C,0x8F,0x3D,0x8F,0xC2,0x75,0x3D,0x08,0xD7,0xA3,0x3C,0x0A,0xD7,0x23,0x3D,0x0C,0xD7,0xA3,0xBC,0x0A,0xD7,0xA3,0x3C, + 0xCE,0xCC,0x4C,0xBD,0x00,0x00,0x00,0x00,0x29,0x5C,0x8F,0xBD,0xCC,0xCC,0x4C,0x3D,0x99,0x99,0x19,0x3E,0xCC,0xCC,0x4C,0x3D,0x8E,0xC2,0xF5,0x3C,0x00,0x00,0x00,0x00, + 0x8F,0xC2,0xF5,0x3D,0xCC,0xCC,0xCC,0x3D,0x8E,0xC2,0x75,0x3D,0xCC,0xCC,0xCC,0x3D,0x8F,0xC2,0xF5,0x3D,0xEB,0x51,0xB8,0x3D,0xEB,0x51,0x38,0x3E,0x00,0x00,0x00,0x00, + 0xEB,0x51,0xB8,0x3D,0xEB,0x51,0x38,0x3E,0xEB,0x51,0xB8,0x3D,0x0A,0xD7,0xA3,0x3C,0x0A,0xD7,0x23,0x3D,0x0A,0xD7,0x23,0x3C,0x8E,0xC2,0xF5,0x3C,0x0A,0xD7,0x23,0x3C, + 0xCC,0xCC,0x4C,0x3D,0x0A,0xD7,0xA3,0x3C,0x08,0xD7,0xA3,0x3C,0xEB,0x51,0x38,0x3E,0x00,0x00,0x80,0x3E,0x90,0xC2,0x75,0x3D,0x3D,0x0A,0x57,0x3E,0x0C,0xD7,0x23,0x3C, + 0x7A,0x14,0x2E,0x3E,0x0C,0xD7,0x23,0x3C,0x0A,0xD7,0x23,0x3D,0x90,0xC2,0xF5,0x3C,0x08,0xD7,0x23,0x3C,0x90,0xC2,0x75,0x3D,0x00,0x00,0x00,0x00,0xAE,0x47,0xE1,0x3D, + 0x08,0xD7,0x23,0x3C,0xB8,0x1E,0x05,0x3E,0x0A,0xD7,0x23,0x3D,0x29,0x5C,0x0F,0x3E,0xEB,0x51,0xB8,0x3D,0x29,0x5C,0x0F,0x3E,0x8F,0xC2,0xF5,0x3D,0xB8,0x1E,0x05,0x3E, + 0x7A,0x14,0x2E,0x3E,0xAE,0x47,0xE1,0x3D,0xCC,0xCC,0x4C,0x3E,0x00,0x00,0x00,0x00,0x7A,0x14,0x2E,0x3E,0x0C,0xD7,0xA3,0x3C,0x5C,0x8F,0x42,0x3E,0x8F,0xC2,0xF5,0x3D, + 0x5C,0x8F,0x42,0x3E,0xB8,0x1E,0x05,0x3E,0x99,0x99,0x19,0x3E,0x8F,0xC2,0xF5,0x3D,0xB8,0x1E,0x05,0x3E,0x29,0x5C,0x0F,0x3E,0x00,0x00,0x00,0x00,0x0C,0xD7,0xA3,0x3C, + 0x3D,0x0A,0x57,0x3E,0xB8,0x1E,0x05,0x3E,0x3D,0x0A,0x57,0x3E,0x29,0x5C,0x8F,0x3D,0xB8,0x1E,0x05,0x3E,0xCD,0xCC,0xCC,0x3D,0xB8,0x1E,0x05,0x3E,0x8F,0xC2,0xF5,0x3D, + 0x8F,0xC2,0xF5,0x3D,0xB8,0x1E,0x05,0x3E,0xAE,0x47,0xE1,0x3D,0x29,0x5C,0x0F,0x3E,0x0A,0xD7,0xA3,0x3D,0xCD,0xCC,0xCC,0x3D,0x3D,0x0A,0x57,0x3E,0x9A,0x99,0x19,0x3E, + 0x28,0x5C,0x8F,0x3D,0xCD,0xCC,0xCC,0x3D,0x00,0x00,0x00,0x00,0x8F,0xC2,0xF5,0x3D,0x3D,0x0A,0x57,0x3E,0xCD,0xCC,0x4C,0x3D,0x28,0x5C,0x0F,0x3E,0xAE,0x47,0xE1,0x3D, + 0xB8,0x1E,0x05,0x3E,0x8F,0xC2,0xF5,0x3D,0xEB,0x51,0x38,0x3E,0x29,0x5C,0x8F,0x3D,0x00,0x00,0x00,0x00,0xB8,0x1E,0x05,0x3E,0x8E,0xC2,0x75,0x3D,0xB8,0x1E,0x05,0x3E, + 0x28,0x5C,0x8F,0x3D,0x8F,0xC2,0xF5,0x3D,0xCC,0xCC,0xCC,0x3D,0x8F,0xC2,0xF5,0x3C,0x8F,0xC2,0xF5,0x3D,0x0C,0xD7,0x23,0x3C,0xCC,0xCC,0xCC,0x3D,0x29,0x5C,0x0F,0x3E, + 0x3D,0x0A,0x57,0x3E,0x0C,0xD7,0x23,0x3C,0xEB,0x51,0x38,0x3E,0x0A,0xD7,0x23,0x3D,0xB8,0x1E,0x05,0x3E,0x0A,0xD7,0xA3,0x3D,0x8F,0xC2,0xF5,0x3D,0xAE,0x47,0xE1,0x3D, + 0xAE,0x47,0xE1,0x3D,0xB8,0x1E,0x05,0x3E,0xEB,0x51,0xB8,0x3D,0x29,0x5C,0x0F,0x3E,0x0A,0xD7,0x23,0x3D,0xB8,0x1E,0x05,0x3E,0x08,0xD7,0xA3,0x3C,0x0C,0xD7,0x23,0x3C, + 0xEB,0x51,0xB8,0x3D,0x90,0xC2,0xF5,0x3C,0xAE,0x47,0xE1,0x3D,0x90,0xC2,0x75,0x3D,0x8F,0xC2,0xF5,0x3D,0x8F,0xC2,0xF5,0x3D,0x28,0x5C,0x0F,0x3E,0xB8,0x1E,0x05,0x3E, + 0x0A,0xD7,0x23,0x3E,0xB8,0x1E,0x05,0x3E,0xEB,0x51,0x38,0x3E,0xB8,0x1E,0x05,0x3E,0x28,0x5C,0x0F,0x3E,0x8F,0xC2,0xF5,0x3D,0xAE,0x47,0xE1,0x3D,0xCD,0xCC,0xCC,0x3D, + 0xEB,0x51,0xB8,0x3D,0x29,0x5C,0x8F,0x3D,0x0A,0xD7,0xA3,0x3D,0x90,0xC2,0x75,0x3D,0x0A,0xD7,0xA3,0x3D,0x90,0xC2,0xF5,0x3C,0xEB,0x51,0xB8,0x3D,0x0C,0xD7,0x23,0x3C, + 0xAE,0x47,0xE1,0x3D,0x29,0x5C,0x8F,0x3D,0x3D,0x0A,0x57,0x3E,0x8F,0xC2,0xF5,0x3D,0x0A,0xD7,0x23,0x3D,0x0A,0xD7,0xA3,0x3C,0xAE,0x47,0xE1,0x3D,0x0A,0xD7,0x23,0x3E, + 0xEB,0x51,0x38,0x3E,0x0A,0xD7,0x23,0x3E,0x00,0x00,0x00,0x00,0xEB,0x51,0x38,0x3E,0x8F,0xC2,0xF5,0x3D,0xEB,0x51,0x38,0x3E,0x8E,0xC2,0x75,0x3D,0x0A,0xD7,0x23,0x3E, + 0xEB,0x51,0xB8,0x3D,0x0A,0xD7,0x23,0x3D,0x3D,0x0A,0x57,0x3E,0xAE,0x47,0xE1,0x3D,0x5C,0x8F,0x42,0x3E,0x8F,0xC2,0xF5,0x3D,0x7A,0x14,0x2E,0x3E,0x8F,0xC2,0xF5,0x3D, + 0x99,0x99,0x19,0x3E,0x8F,0xC2,0x75,0x3D,0xCC,0xCC,0xCC,0x3D,0x8F,0xC2,0x75,0x3D,0x28,0x5C,0x8F,0x3D,0xCC,0xCC,0x4C,0x3D,0x08,0xD7,0x23,0x3C,0x29,0x5C,0x8F,0x3D, + 0x08,0xD7,0x23,0x3C,0xEB,0x51,0xB8,0x3D,0x99,0x99,0x19,0x3E,0x28,0x5C,0x8F,0x3D,0x0A,0xD7,0x23,0x3E,0x0A,0xD7,0x23,0x3D,0x0A,0xD7,0x23,0x3E,0x09,0xD7,0xA3,0x3C, + 0x99,0x99,0x19,0x3E,0x00,0x00,0x00,0x00,0x0A,0xD7,0xA3,0x3D,0x08,0xD7,0x23,0x3C,0x8E,0xC2,0x75,0x3D,0x8E,0xC2,0xF5,0x3C,0xCC,0xCC,0x4C,0x3D,0x8E,0xC2,0x75,0x3D, + 0xCC,0xCC,0x4C,0x3D,0x0A,0xD7,0xA3,0x3D,0x8E,0xC2,0x75,0x3D,0xEB,0x51,0xB8,0x3D,0x0A,0xD7,0xA3,0x3D,0x09,0xD7,0xA3,0x3C,0x8E,0xC2,0x75,0x3D,0xCC,0xCC,0xCC,0x3D, + 0x0A,0xD7,0x23,0x3E,0xEB,0x51,0xB8,0x3D,0x8E,0xC2,0x75,0x3D,0xAE,0x47,0xE1,0x3D,0xCC,0xCC,0x4C,0x3D,0xB8,0x1E,0x05,0x3E,0xCC,0xCC,0x4C,0x3D,0x0A,0xD7,0x23,0x3E, + 0xCC,0xCC,0xCC,0x3D,0x0A,0xD7,0x23,0x3E,0x8F,0xC2,0xF5,0x3D,0x99,0x99,0x19,0x3E,0x99,0x99,0x19,0x3E,0x28,0x5C,0x0F,0x3E,0x7A,0x14,0x2E,0x3E,0x90,0xC2,0xF5,0x3C, + 0x28,0x5C,0x8F,0x3D,0x29,0x5C,0x0F,0x3E,0x99,0x99,0x19,0x3E,0xB8,0x1E,0x05,0x3E,0xB8,0x1E,0x05,0x3E,0xEC,0x51,0xB8,0x3D,0xAE,0x47,0xE1,0x3D,0x9A,0x99,0x19,0x3E, + 0x0A,0xD7,0x23,0x3E,0x00,0x00,0x00,0x00,0xB8,0x1E,0x05,0x3E,0x0C,0xD7,0xA3,0x3C,0x8E,0xC2,0xF5,0x3C,0x0A,0xD7,0x23,0x3D,0x08,0xD7,0x23,0x3C,0x9A,0x99,0x19,0x3E, + 0xCC,0xCC,0x4C,0x3D,0x29,0x5C,0x0F,0x3E,0xB8,0x1E,0x05,0x3E,0x0A,0xD7,0xA3,0x3D,0xAE,0x47,0xE1,0x3D,0x9A,0x99,0x19,0x3E,0x0A,0xD7,0xA3,0x3D,0xCD,0xCC,0xCC,0x3D, + 0x0A,0xD7,0xA3,0x3D,0x29,0x5C,0x0F,0x3E,0xAE,0x47,0xE1,0x3D,0xCC,0xCC,0xCC,0x3D,0xCC,0xCC,0x4C,0x3D,0xEB,0x51,0xB8,0x3D,0x08,0xD7,0xA3,0x3C,0x0A,0xD7,0xA3,0x3D, + 0x08,0xD7,0x23,0x3C,0x00,0x00,0x00,0x00,0xCC,0xCC,0x4C,0x3D,0xCD,0xCC,0x4C,0x3D,0x8F,0xC2,0xF5,0x3D,0x8F,0xC2,0xF5,0x3D,0x00,0x00,0x00,0x00,0x0A,0xD7,0x23,0x3E, + 0x3D,0x0A,0x57,0x3E,0x0A,0xD7,0x23,0x3E,0x0A,0xD7,0xA3,0x3D,0x0A,0xD7,0x23,0x3E,0xB8,0x1E,0x05,0x3E,0x29,0x5C,0x0F,0x3E,0x28,0x5C,0x0F,0x3E,0xB8,0x1E,0x05,0x3E, + 0x8F,0xC2,0xF5,0x3D,0xEC,0x51,0xB8,0x3D,0xCC,0xCC,0xCC,0x3D,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0x3D,0xEB,0x51,0xB8,0x3D,0x0A,0xD7,0x23,0x3D,0x9A,0x99,0x19,0x3E, + 0x0C,0xD7,0xA3,0xBC,0xCC,0xCC,0x4C,0x3E,0x3D,0x0A,0x57,0x3E,0x0A,0xD7,0x23,0x3C,0x00,0x00,0x80,0x3E,0x29,0x5C,0x0F,0x3E,0x90,0xC2,0xF5,0xBC,0x8F,0xC2,0x75,0x3D, + 0x00,0x00,0x80,0x3E,0x8F,0xC2,0x75,0x3D,0x29,0x5C,0x8F,0xBD,0x0A,0xD7,0xA3,0x3D,0x1E,0x85,0x6B,0x3E,0xEB,0x51,0x38,0x3E,0x29,0x5C,0x8F,0xBD,0x0A,0xD7,0xA3,0x3C, + 0x0A,0xD7,0x23,0x3E,0x0A,0xD7,0xA3,0x3C,0x8F,0xC2,0xF5,0x3D,0x0A,0xD7,0x23,0x3C,0xB8,0x1E,0x05,0x3E,0x8F,0xC2,0xF5,0x3C,0xB8,0x1E,0x05,0x3E,0x29,0x5C,0x8F,0x3D, + 0x28,0x5C,0x0F,0x3E,0x8F,0xC2,0xF5,0x3D,0x0A,0xD7,0xA3,0x3D,0xAE,0x47,0xE1,0x3D,0x8E,0xC2,0xF5,0x3C,0xEB,0x51,0xB8,0x3D,0x08,0xD7,0x23,0x3C,0xAE,0x47,0xE1,0x3D, + 0x8F,0xC2,0xF5,0x3D,0x8F,0xC2,0xF5,0x3C,0x7A,0x14,0x2E,0x3E,0x8F,0xC2,0xF5,0x3C,0x00,0x00,0x00,0x00,0x8F,0xC2,0xF5,0x3D,0x0C,0xD7,0xA3,0xBC,0xAE,0x47,0xE1,0x3D, + 0xCE,0xCC,0x4C,0xBD,0xCC,0xCC,0xCC,0x3D,0x8E,0xC2,0x75,0xBD,0x0A,0xD7,0xA3,0x3D,0x29,0x5C,0x8F,0xBD,0xCC,0xCC,0x4C,0x3D,0x29,0x5C,0x8F,0xBD,0x8F,0xC2,0xF5,0x3C, + 0x8E,0xC2,0x75,0xBD,0xAE,0x47,0xE1,0x3D,0xCC,0xCC,0xCC,0x3D,0xAE,0x47,0xE1,0x3D,0x00,0x00,0x00,0x00,0x0A,0xD7,0x23,0x3C,0xAE,0x47,0x61,0x3E,0xCC,0xCC,0x4C,0x3D, + 0xCC,0xCC,0x4C,0x3E,0xCC,0xCC,0x4C,0x3D,0xAE,0x47,0x61,0x3E,0xCC,0xCC,0x4C,0x3D,0x90,0xC2,0xF5,0xBC,0x0A,0xD7,0x23,0x3D,0x8E,0xC2,0x75,0xBD,0x0A,0xD7,0xA3,0x3C, + 0x29,0x5C,0x8F,0xBD,0x0A,0xD7,0x23,0x3D,0x0A,0xD7,0xA3,0x3D,0x0A,0xD7,0x23,0x3E,0x28,0x5C,0x0F,0x3E,0x3D,0x0A,0x57,0x3E,0xB8,0x1E,0x05,0x3E,0xAE,0x47,0x61,0x3E, + 0xCC,0xCC,0xCC,0x3D,0xAE,0x47,0x61,0x3E,0x00,0x00,0x00,0x00,0x8F,0xC2,0xF5,0x3D,0x29,0x5C,0x8F,0xBD,0x8E,0xC2,0xF5,0x3C,0x0A,0xD7,0xA3,0x3D,0x0A,0xD7,0xA3,0x3D, + 0x28,0x5C,0x8F,0x3D,0x08,0xD7,0x23,0x3C,0x08,0xD7,0x23,0x3C,0x8F,0xC2,0xF5,0x3C,0x0A,0xD7,0x23,0x3D,0xAE,0x47,0xE1,0x3D,0x28,0x5C,0x0F,0x3E,0x8F,0xC2,0xF5,0x3C, + 0x8E,0xC2,0x75,0x3E,0x0A,0xD7,0xA3,0x3C,0x7A,0x14,0x2E,0x3E,0x8F,0xC2,0xF5,0x3C,0x0A,0xD7,0x23,0x3E,0x0A,0xD7,0xA3,0x3C,0xCC,0xCC,0xCC,0x3D,0x0A,0xD7,0xA3,0x3C, + 0xAE,0x47,0x61,0x3E,0x8F,0xC2,0xF5,0x3C,0xEB,0x51,0x38,0x3E,0x0A,0xD7,0x23,0x3D,0x7A,0x14,0x2E,0x3E,0xCC,0xCC,0x4C,0x3D,0xB8,0x1E,0x05,0x3E,0x0A,0xD7,0x23,0x3D, + 0xAE,0x47,0xE1,0x3D,0x0A,0xD7,0x23,0x3D,0x28,0x5C,0x8F,0x3D,0xCC,0xCC,0x4C,0x3D,0xCC,0xCC,0x4C,0x3D,0x0A,0xD7,0xA3,0x3C,0x0C,0xD7,0xA3,0xBC,0x0A,0xD7,0xA3,0x3C, + 0x0A,0xD7,0x23,0xBD,0x0A,0xD7,0xA3,0x3C,0x0A,0xD7,0xA3,0x3D,0x0A,0xD7,0x23,0x3D,0x8E,0xC2,0x75,0x3D,0x0A,0xD7,0xA3,0x3C,0x8E,0xC2,0x75,0x3E,0x8F,0xC2,0xF5,0x3C, + 0x1E,0x85,0x6B,0x3E,0x0A,0xD7,0x23,0x3D,0x5C,0x8F,0x42,0x3E,0x8F,0xC2,0xF5,0x3C,0xCC,0xCC,0xCC,0x3D,0x8F,0xC2,0xF5,0x3C,0xAE,0x47,0x61,0x3E,0xCC,0xCC,0x4C,0x3D, + 0xEB,0x51,0xB8,0x3D,0x0A,0xD7,0xA3,0x3C,0x00,0x00,0x00,0x00,0x8F,0xC2,0xF5,0x3C,0x0A,0xD7,0x23,0xBD,0x0A,0xD7,0xA3,0x3C,0x8E,0xC2,0x75,0xBD,0xAE,0x47,0xE1,0x3D, + 0x0A,0xD7,0xA3,0x3D,0x7A,0x14,0x2E,0x3E,0x0A,0xD7,0xA3,0x3D,0xEB,0x51,0x38,0x3E,0xCC,0xCC,0xCC,0x3D,0xCC,0xCC,0x4C,0x3D,0xAE,0x47,0xE1,0x3D,0x28,0x5C,0x8F,0x3D, + 0xCC,0xCC,0xCC,0x3D,0xAE,0x47,0xE1,0x3D,0x28,0x5C,0x8F,0x3D,0x99,0x99,0x19,0x3E,0x8E,0xC2,0x75,0x3D,0x7A,0x14,0x2E,0x3E,0x28,0x5C,0x8F,0x3D,0xAE,0x47,0xE1,0x3D, + 0x3D,0x0A,0x57,0x3E,0x9A,0x99,0x19,0x3E,0x3D,0x0A,0x57,0x3E,0x21,0x0A,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x03,0x00,0x04,0x00,0x04,0x00,0x05,0x00,0x05, + 0x00,0x02,0x00,0x22,0x04,0x00,0x06,0x00,0x07,0x00,0x08,0x00,0x09,0x00,0x23,0x08,0x00,0x0A,0x00,0x0B,0x00,0x0C,0x00,0x0D,0x00,0x0E,0x00,0x0F,0x00,0x10,0x00,0x11, + 0x00,0x24,0x2A,0x00,0x12,0x00,0x13,0x00,0x14,0x00,0x15,0x00,0x16,0x00,0x17,0x00,0x17,0x00,0x18,0x00,0x18,0x00,0x19,0x00,0x19,0x00,0x1A,0x00,0x1A,0x00,0x1B,0x00, + 0x1B,0x00,0x1C,0x00,0x1C,0x00,0x1D,0x00,0x1D,0x00,0x1E,0x00,0x1E,0x00,0x1F,0x00,0x1F,0x00,0x20,0x00,0x20,0x00,0x21,0x00,0x21,0x00,0x22,0x00,0x22,0x00,0x11,0x00, + 0x11,0x00,0x23,0x00,0x23,0x00,0x24,0x00,0x24,0x00,0x25,0x00,0x25,0x00,0x26,0x00,0x26,0x00,0x05,0x00,0x05,0x00,0x27,0x00,0x25,0x34,0x00,0x28,0x00,0x29,0x00,0x19, + 0x00,0x2A,0x00,0x2A,0x00,0x2B,0x00,0x2B,0x00,0x2C,0x00,0x2C,0x00,0x2D,0x00,0x2D,0x00,0x2E,0x00,0x2E,0x00,0x1C,0x00,0x1C,0x00,0x1B,0x00,0x1B,0x00,0x2F,0x00,0x2F, + 0x00,0x30,0x00,0x30,0x00,0x19,0x00,0x19,0x00,0x31,0x00,0x31,0x00,0x32,0x00,0x32,0x00,0x33,0x00,0x33,0x00,0x34,0x00,0x34,0x00,0x28,0x00,0x35,0x00,0x36,0x00,0x36, + 0x00,0x37,0x00,0x37,0x00,0x38,0x00,0x38,0x00,0x39,0x00,0x39,0x00,0x3A,0x00,0x3A,0x00,0x3B,0x00,0x3B,0x00,0x3C,0x00,0x3C,0x00,0x3D,0x00,0x3D,0x00,0x3E,0x00,0x3E, + 0x00,0x35,0x00,0x26,0x3C,0x00,0x3F,0x00,0x40,0x00,0x40,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x42,0x00,0x43,0x00,0x43,0x00,0x44,0x00,0x44,0x00,0x11,0x00,0x11,0x00, + 0x45,0x00,0x45,0x00,0x46,0x00,0x46,0x00,0x47,0x00,0x47,0x00,0x48,0x00,0x48,0x00,0x05,0x00,0x05,0x00,0x02,0x00,0x02,0x00,0x49,0x00,0x49,0x00,0x10,0x00,0x10,0x00, + 0x4A,0x00,0x4A,0x00,0x4B,0x00,0x4B,0x00,0x4C,0x00,0x4C,0x00,0x4D,0x00,0x4D,0x00,0x4E,0x00,0x4E,0x00,0x4F,0x00,0x4F,0x00,0x50,0x00,0x50,0x00,0x08,0x00,0x08,0x00, + 0x51,0x00,0x51,0x00,0x52,0x00,0x52,0x00,0x53,0x00,0x53,0x00,0x54,0x00,0x54,0x00,0x55,0x00,0x55,0x00,0x56,0x00,0x56,0x00,0x57,0x00,0x57,0x00,0x58,0x00,0x27,0x0C, + 0x00,0x59,0x00,0x5A,0x00,0x5A,0x00,0x00,0x00,0x00,0x00,0x1A,0x00,0x1A,0x00,0x5B,0x00,0x5B,0x00,0x5C,0x00,0x5C,0x00,0x5D,0x00,0x28,0x12,0x00,0x5E,0x00,0x5F,0x00, + 0x5F,0x00,0x60,0x00,0x60,0x00,0x5C,0x00,0x5C,0x00,0x61,0x00,0x61,0x00,0x62,0x00,0x62,0x00,0x02,0x00,0x02,0x00,0x63,0x00,0x63,0x00,0x64,0x00,0x64,0x00,0x0D,0x00, + 0x29,0x12,0x00,0x65,0x00,0x66,0x00,0x66,0x00,0x67,0x00,0x67,0x00,0x68,0x00,0x68,0x00,0x69,0x00,0x69,0x00,0x6A,0x00,0x6A,0x00,0x6B,0x00,0x6B,0x00,0x6C,0x00,0x6C, + 0x00,0x6D,0x00,0x6D,0x00,0x6E,0x00,0x2A,0x06,0x00,0x6F,0x00,0x70,0x00,0x71,0x00,0x72,0x00,0x73,0x00,0x10,0x00,0x2B,0x04,0x00,0x74,0x00,0x25,0x00,0x75,0x00,0x76, + 0x00,0x2C,0x0C,0x00,0x77,0x00,0x78,0x00,0x78,0x00,0x49,0x00,0x49,0x00,0x79,0x00,0x79,0x00,0x77,0x00,0x77,0x00,0x7A,0x00,0x7A,0x00,0x29,0x00,0x2D,0x02,0x00,0x75, + 0x00,0x76,0x00,0x2E,0x08,0x00,0x79,0x00,0x49,0x00,0x49,0x00,0x78,0x00,0x78,0x00,0x77,0x00,0x77,0x00,0x79,0x00,0x2F,0x02,0x00,0x7B,0x00,0x6E,0x00,0x30,0x20,0x00, + 0x7C,0x00,0x60,0x00,0x60,0x00,0x7D,0x00,0x7D,0x00,0x71,0x00,0x71,0x00,0x75,0x00,0x75,0x00,0x7E,0x00,0x7E,0x00,0x7F,0x00,0x7F,0x00,0x80,0x00,0x80,0x00,0x47,0x00, + 0x47,0x00,0x81,0x00,0x81,0x00,0x82,0x00,0x82,0x00,0x83,0x00,0x83,0x00,0x84,0x00,0x84,0x00,0x85,0x00,0x85,0x00,0x86,0x00,0x86,0x00,0x08,0x00,0x08,0x00,0x7C,0x00, + 0x31,0x06,0x00,0x87,0x00,0x5B,0x00,0x5B,0x00,0x19,0x00,0x19,0x00,0x26,0x00,0x32,0x1A,0x00,0x5C,0x00,0x7D,0x00,0x7D,0x00,0x88,0x00,0x88,0x00,0x60,0x00,0x60,0x00, + 0x19,0x00,0x19,0x00,0x18,0x00,0x18,0x00,0x86,0x00,0x86,0x00,0x89,0x00,0x89,0x00,0x85,0x00,0x85,0x00,0x8A,0x00,0x8A,0x00,0x8B,0x00,0x8B,0x00,0x20,0x00,0x20,0x00, + 0x29,0x00,0x29,0x00,0x8C,0x00,0x33,0x1C,0x00,0x8D,0x00,0x8E,0x00,0x8E,0x00,0x8F,0x00,0x8F,0x00,0x90,0x00,0x90,0x00,0x91,0x00,0x91,0x00,0x92,0x00,0x92,0x00,0x93, + 0x00,0x93,0x00,0x11,0x00,0x11,0x00,0x56,0x00,0x56,0x00,0x81,0x00,0x81,0x00,0x47,0x00,0x47,0x00,0x26,0x00,0x26,0x00,0x05,0x00,0x05,0x00,0x02,0x00,0x02,0x00,0x49, + 0x00,0x34,0x06,0x00,0x94,0x00,0x62,0x00,0x62,0x00,0x95,0x00,0x94,0x00,0x96,0x00,0x35,0x20,0x00,0x97,0x00,0x8D,0x00,0x8D,0x00,0x0E,0x00,0x0E,0x00,0x1E,0x00,0x1E, + 0x00,0x98,0x00,0x98,0x00,0x09,0x00,0x09,0x00,0x99,0x00,0x99,0x00,0x92,0x00,0x92,0x00,0x93,0x00,0x93,0x00,0x11,0x00,0x11,0x00,0x56,0x00,0x56,0x00,0x81,0x00,0x81, + 0x00,0x47,0x00,0x47,0x00,0x26,0x00,0x26,0x00,0x05,0x00,0x05,0x00,0x02,0x00,0x02,0x00,0x49,0x00,0x36,0x2C,0x00,0x9A,0x00,0x86,0x00,0x86,0x00,0x08,0x00,0x08,0x00, + 0x7C,0x00,0x7C,0x00,0x60,0x00,0x60,0x00,0x7D,0x00,0x7D,0x00,0x71,0x00,0x71,0x00,0x62,0x00,0x62,0x00,0x78,0x00,0x78,0x00,0x7F,0x00,0x7F,0x00,0x80,0x00,0x80,0x00, + 0x9B,0x00,0x9B,0x00,0x46,0x00,0x46,0x00,0x45,0x00,0x45,0x00,0x9C,0x00,0x9C,0x00,0x9D,0x00,0x9D,0x00,0x9E,0x00,0x9E,0x00,0x73,0x00,0x73,0x00,0x8F,0x00,0x8F,0x00, + 0x54,0x00,0x54,0x00,0x9F,0x00,0x9F,0x00,0xA0,0x00,0xA0,0x00,0x62,0x00,0x37,0x04,0x00,0xA1,0x00,0x48,0x00,0x06,0x00,0xA1,0x00,0x38,0x38,0x00,0x19,0x00,0x1A,0x00, + 0x1A,0x00,0xA2,0x00,0xA2,0x00,0x5C,0x00,0x5C,0x00,0x2E,0x00,0x2E,0x00,0xA3,0x00,0xA3,0x00,0xA4,0x00,0xA4,0x00,0xA5,0x00,0xA5,0x00,0xA6,0x00,0xA6,0x00,0x35,0x00, + 0x35,0x00,0xA7,0x00,0xA7,0x00,0xA8,0x00,0xA8,0x00,0x24,0x00,0x24,0x00,0x25,0x00,0x25,0x00,0x26,0x00,0x26,0x00,0x05,0x00,0x05,0x00,0x02,0x00,0x02,0x00,0x49,0x00, + 0x49,0x00,0x62,0x00,0x62,0x00,0xA9,0x00,0xA9,0x00,0xAA,0x00,0xAA,0x00,0xAB,0x00,0xAB,0x00,0x90,0x00,0x90,0x00,0xAC,0x00,0xAC,0x00,0xAD,0x00,0xAD,0x00,0xAE,0x00, + 0xAE,0x00,0x17,0x00,0x17,0x00,0x18,0x00,0x18,0x00,0x19,0x00,0x39,0x2C,0x00,0xAF,0x00,0xB0,0x00,0xB0,0x00,0xB1,0x00,0xB1,0x00,0xB2,0x00,0xB2,0x00,0xB3,0x00,0xB3, + 0x00,0xB4,0x00,0xB4,0x00,0xB5,0x00,0xB5,0x00,0x07,0x00,0x07,0x00,0x5D,0x00,0x5D,0x00,0xA2,0x00,0xA2,0x00,0x60,0x00,0x60,0x00,0x7C,0x00,0x7C,0x00,0xB6,0x00,0xB6, + 0x00,0x50,0x00,0x50,0x00,0x9A,0x00,0x9A,0x00,0xAF,0x00,0xAF,0x00,0xA6,0x00,0xA6,0x00,0xB7,0x00,0xB7,0x00,0x46,0x00,0x46,0x00,0x9B,0x00,0x9B,0x00,0x26,0x00,0x26, + 0x00,0x05,0x00,0x05,0x00,0x78,0x00,0x3A,0x10,0x00,0x0E,0x00,0x61,0x00,0x61,0x00,0xA0,0x00,0xA0,0x00,0xB8,0x00,0xB8,0x00,0x0E,0x00,0x79,0x00,0x49,0x00,0x49,0x00, + 0x78,0x00,0x78,0x00,0x77,0x00,0x77,0x00,0x79,0x00,0x3B,0x14,0x00,0x0E,0x00,0x61,0x00,0x61,0x00,0xA0,0x00,0xA0,0x00,0xB8,0x00,0xB8,0x00,0x0E,0x00,0x77,0x00,0x78, + 0x00,0x78,0x00,0x49,0x00,0x49,0x00,0x79,0x00,0x79,0x00,0x77,0x00,0x77,0x00,0x7A,0x00,0x7A,0x00,0x29,0x00,0x3C,0x04,0x00,0xB9,0x00,0x75,0x00,0x75,0x00,0xBA,0x00, + 0x3D,0x04,0x00,0x71,0x00,0xBB,0x00,0x10,0x00,0xBC,0x00,0x3E,0x04,0x00,0x1B,0x00,0xBD,0x00,0xBD,0x00,0x29,0x00,0x3F,0x22,0x00,0x1C,0x00,0x87,0x00,0x87,0x00,0x59, + 0x00,0x59,0x00,0x1A,0x00,0x1A,0x00,0xBE,0x00,0xBE,0x00,0x08,0x00,0x08,0x00,0x50,0x00,0x50,0x00,0xBF,0x00,0xBF,0x00,0xC0,0x00,0xC0,0x00,0xC1,0x00,0xC1,0x00,0x99, + 0x00,0x99,0x00,0x73,0x00,0x73,0x00,0xC2,0x00,0xC2,0x00,0xC3,0x00,0x6B,0x00,0xC4,0x00,0xC4,0x00,0x80,0x00,0x80,0x00,0xC5,0x00,0xC5,0x00,0x6B,0x00,0x40,0x34,0x00, + 0x90,0x00,0xC6,0x00,0xC6,0x00,0xC7,0x00,0xC7,0x00,0xC8,0x00,0xC8,0x00,0xC9,0x00,0xC9,0x00,0x1D,0x00,0x1D,0x00,0x61,0x00,0x61,0x00,0xCA,0x00,0xCA,0x00,0xCB,0x00, + 0xCB,0x00,0xCC,0x00,0xCC,0x00,0xCD,0x00,0xCD,0x00,0xCE,0x00,0xCE,0x00,0xCF,0x00,0xC8,0x00,0x2E,0x00,0x2E,0x00,0xB5,0x00,0xB5,0x00,0x4A,0x00,0x4A,0x00,0xD0,0x00, + 0xD0,0x00,0xCC,0x00,0xD1,0x00,0xCF,0x00,0xCF,0x00,0xD2,0x00,0xD2,0x00,0xD3,0x00,0xD3,0x00,0xD4,0x00,0xD4,0x00,0x95,0x00,0x95,0x00,0xD5,0x00,0xD5,0x00,0xD6,0x00, + 0xD6,0x00,0xD7,0x00,0xD7,0x00,0xD8,0x00,0x41,0x06,0x00,0x08,0x00,0x29,0x00,0x08,0x00,0xBA,0x00,0xD9,0x00,0x9D,0x00,0x42,0x24,0x00,0x06,0x00,0x29,0x00,0x06,0x00, + 0x18,0x00,0x18,0x00,0x17,0x00,0x17,0x00,0x33,0x00,0x33,0x00,0xD8,0x00,0xD8,0x00,0xDA,0x00,0xDA,0x00,0xDB,0x00,0xDB,0x00,0x91,0x00,0x91,0x00,0xDC,0x00,0x61,0x00, + 0xDC,0x00,0xDC,0x00,0x9E,0x00,0x9E,0x00,0xA6,0x00,0xA6,0x00,0x35,0x00,0x35,0x00,0xA7,0x00,0xA7,0x00,0xA8,0x00,0xA8,0x00,0x24,0x00,0x24,0x00,0x25,0x00,0x25,0x00, + 0x29,0x00,0x43,0x22,0x00,0xDD,0x00,0x16,0x00,0x16,0x00,0x17,0x00,0x17,0x00,0x94,0x00,0x94,0x00,0x7C,0x00,0x7C,0x00,0x67,0x00,0x67,0x00,0x5B,0x00,0x5B,0x00,0x5C, + 0x00,0x5C,0x00,0xDE,0x00,0xDE,0x00,0xCA,0x00,0xCA,0x00,0x79,0x00,0x79,0x00,0xDF,0x00,0xDF,0x00,0xE0,0x00,0xE0,0x00,0x80,0x00,0x80,0x00,0x96,0x00,0x96,0x00,0x24, + 0x00,0x24,0x00,0x23,0x00,0x23,0x00,0xE1,0x00,0x44,0x18,0x00,0x06,0x00,0x29,0x00,0x06,0x00,0xB6,0x00,0xB6,0x00,0x50,0x00,0x50,0x00,0x9A,0x00,0x9A,0x00,0xAD,0x00, + 0xAD,0x00,0xE2,0x00,0xE2,0x00,0x93,0x00,0x93,0x00,0xD4,0x00,0xD4,0x00,0x45,0x00,0x45,0x00,0x46,0x00,0x46,0x00,0x9B,0x00,0x9B,0x00,0x29,0x00,0x45,0x08,0x00,0x06, + 0x00,0x29,0x00,0x06,0x00,0x8E,0x00,0x61,0x00,0xE3,0x00,0x29,0x00,0x39,0x00,0x46,0x06,0x00,0x06,0x00,0x29,0x00,0x06,0x00,0x8E,0x00,0x61,0x00,0xE3,0x00,0x47,0x26, + 0x00,0xDD,0x00,0x16,0x00,0x16,0x00,0x17,0x00,0x17,0x00,0x94,0x00,0x94,0x00,0x7C,0x00,0x7C,0x00,0x67,0x00,0x67,0x00,0x5B,0x00,0x5B,0x00,0x5C,0x00,0x5C,0x00,0xDE, + 0x00,0xDE,0x00,0xCA,0x00,0xCA,0x00,0x79,0x00,0x79,0x00,0xDF,0x00,0xDF,0x00,0xE0,0x00,0xE0,0x00,0x80,0x00,0x80,0x00,0x96,0x00,0x96,0x00,0x24,0x00,0x24,0x00,0x23, + 0x00,0x23,0x00,0xE1,0x00,0xE1,0x00,0xE4,0x00,0xE5,0x00,0xE4,0x00,0x48,0x06,0x00,0x06,0x00,0x29,0x00,0xA1,0x00,0x8C,0x00,0x61,0x00,0xE6,0x00,0x49,0x02,0x00,0x06, + 0x00,0x29,0x00,0x4A,0x12,0x00,0x94,0x00,0xE7,0x00,0xE7,0x00,0xE8,0x00,0xE8,0x00,0xE9,0x00,0xE9,0x00,0x80,0x00,0x80,0x00,0x48,0x00,0x48,0x00,0x05,0x00,0x05,0x00, + 0x02,0x00,0x02,0x00,0xEA,0x00,0xEA,0x00,0x62,0x00,0x4B,0x06,0x00,0x06,0x00,0x29,0x00,0xA1,0x00,0x62,0x00,0xEB,0x00,0x8C,0x00,0x4C,0x04,0x00,0x06,0x00,0x29,0x00, + 0x29,0x00,0xEC,0x00,0x4D,0x08,0x00,0x06,0x00,0x29,0x00,0x06,0x00,0x47,0x00,0xED,0x00,0x47,0x00,0xED,0x00,0xBA,0x00,0x4E,0x06,0x00,0x06,0x00,0x29,0x00,0x06,0x00, + 0x8C,0x00,0xA1,0x00,0x8C,0x00,0x4F,0x28,0x00,0x7C,0x00,0x67,0x00,0x67,0x00,0x5B,0x00,0x5B,0x00,0x5C,0x00,0x5C,0x00,0xDE,0x00,0xDE,0x00,0xCA,0x00,0xCA,0x00,0x79, + 0x00,0x79,0x00,0xDF,0x00,0xDF,0x00,0xE0,0x00,0xE0,0x00,0x80,0x00,0x80,0x00,0x96,0x00,0x96,0x00,0x24,0x00,0x24,0x00,0x23,0x00,0x23,0x00,0xE1,0x00,0xE1,0x00,0xEE, + 0x00,0xEE,0x00,0xEF,0x00,0xEF,0x00,0xDD,0x00,0xDD,0x00,0x16,0x00,0x16,0x00,0x17,0x00,0x17,0x00,0x94,0x00,0x94,0x00,0x7C,0x00,0x50,0x14,0x00,0x06,0x00,0x29,0x00, + 0x06,0x00,0x18,0x00,0x18,0x00,0x17,0x00,0x17,0x00,0x33,0x00,0x33,0x00,0xD8,0x00,0xD8,0x00,0xF0,0x00,0xF0,0x00,0xF1,0x00,0xF1,0x00,0xB0,0x00,0xB0,0x00,0xF2,0x00, + 0xF2,0x00,0xF3,0x00,0x51,0x2A,0x00,0x7C,0x00,0x67,0x00,0x67,0x00,0x5B,0x00,0x5B,0x00,0x5C,0x00,0x5C,0x00,0xDE,0x00,0xDE,0x00,0xCA,0x00,0xCA,0x00,0x79,0x00,0x79, + 0x00,0xDF,0x00,0xDF,0x00,0xE0,0x00,0xE0,0x00,0x80,0x00,0x80,0x00,0x96,0x00,0x96,0x00,0x24,0x00,0x24,0x00,0x23,0x00,0x23,0x00,0xE1,0x00,0xE1,0x00,0xEE,0x00,0xEE, + 0x00,0xEF,0x00,0xEF,0x00,0xDD,0x00,0xDD,0x00,0x16,0x00,0x16,0x00,0x17,0x00,0x17,0x00,0x94,0x00,0x94,0x00,0x7C,0x00,0xF4,0x00,0xF5,0x00,0x52,0x16,0x00,0x06,0x00, + 0x29,0x00,0x06,0x00,0x18,0x00,0x18,0x00,0x17,0x00,0x17,0x00,0x33,0x00,0x33,0x00,0xD8,0x00,0xD8,0x00,0xDA,0x00,0xDA,0x00,0xDB,0x00,0xDB,0x00,0x91,0x00,0x91,0x00, + 0xDC,0x00,0xDC,0x00,0x61,0x00,0x69,0x00,0x8C,0x00,0x53,0x26,0x00,0x16,0x00,0x17,0x00,0x17,0x00,0x18,0x00,0x18,0x00,0x19,0x00,0x19,0x00,0x1A,0x00,0x1A,0x00,0x1B, + 0x00,0x1B,0x00,0x1C,0x00,0x1C,0x00,0x1D,0x00,0x1D,0x00,0x1E,0x00,0x1E,0x00,0x1F,0x00,0x1F,0x00,0x20,0x00,0x20,0x00,0x21,0x00,0x21,0x00,0x22,0x00,0x22,0x00,0x11, + 0x00,0x11,0x00,0x23,0x00,0x23,0x00,0x24,0x00,0x24,0x00,0x25,0x00,0x25,0x00,0x26,0x00,0x26,0x00,0x05,0x00,0x05,0x00,0x27,0x00,0x54,0x04,0x00,0xB6,0x00,0x9B,0x00, + 0x06,0x00,0xA1,0x00,0x55,0x12,0x00,0x06,0x00,0x10,0x00,0x10,0x00,0x78,0x00,0x78,0x00,0x7F,0x00,0x7F,0x00,0x80,0x00,0x80,0x00,0x47,0x00,0x47,0x00,0x81,0x00,0x81, + 0x00,0x56,0x00,0x56,0x00,0x11,0x00,0x11,0x00,0xA1,0x00,0x56,0x04,0x00,0x06,0x00,0x47,0x00,0xED,0x00,0x47,0x00,0x57,0x08,0x00,0x06,0x00,0x26,0x00,0x94,0x00,0x26, + 0x00,0x94,0x00,0x3A,0x00,0xF6,0x00,0x3A,0x00,0x58,0x04,0x00,0x06,0x00,0x8C,0x00,0xA1,0x00,0x29,0x00,0x59,0x06,0x00,0x06,0x00,0xE3,0x00,0xE3,0x00,0x47,0x00,0xED, + 0x00,0xE3,0x00,0x5A,0x06,0x00,0xA1,0x00,0x29,0x00,0x06,0x00,0xA1,0x00,0x29,0x00,0x8C,0x00,0x5B,0x08,0x00,0x65,0x00,0x6E,0x00,0xF7,0x00,0x0B,0x00,0x65,0x00,0x5E, + 0x00,0x6E,0x00,0x0D,0x00,0x5C,0x02,0x00,0x06,0x00,0xF8,0x00,0x5D,0x08,0x00,0xF9,0x00,0xFA,0x00,0x5E,0x00,0x0D,0x00,0x65,0x00,0x5E,0x00,0x6E,0x00,0x0D,0x00,0x5E, + 0x04,0x00,0xFB,0x00,0x75,0x00,0xFB,0x00,0xBD,0x00,0x5F,0x02,0x00,0x6E,0x00,0xFC,0x00,0x60,0x0C,0x00,0xFD,0x00,0x07,0x00,0x07,0x00,0x71,0x00,0x71,0x00,0xB5,0x00, + 0xB5,0x00,0xFE,0x00,0xFE,0x00,0xFF,0x00,0xFF,0x00,0x71,0x00,0x61,0x1C,0x00,0xAC,0x00,0xEC,0x00,0xB0,0x00,0x90,0x00,0x90,0x00,0x09,0x00,0x09,0x00,0x98,0x00,0x98, + 0x00,0x00,0x01,0x00,0x01,0xB5,0x00,0xB5,0x00,0xCA,0x00,0xCA,0x00,0x10,0x00,0x10,0x00,0x78,0x00,0x78,0x00,0x7F,0x00,0x7F,0x00,0x26,0x00,0x26,0x00,0x47,0x00,0x47, + 0x00,0x46,0x00,0x46,0x00,0x45,0x00,0x62,0x1C,0x00,0x06,0x00,0x29,0x00,0x61,0x00,0x1E,0x00,0x1E,0x00,0x2D,0x00,0x2D,0x00,0x01,0x01,0x01,0x01,0x4C,0x00,0x4C,0x00, + 0xA5,0x00,0xA5,0x00,0x02,0x01,0x02,0x01,0x36,0x00,0x36,0x00,0x03,0x01,0x03,0x01,0x04,0x01,0x04,0x01,0x9B,0x00,0x9B,0x00,0x48,0x00,0x48,0x00,0x05,0x00,0x05,0x00, + 0x27,0x00,0x63,0x1A,0x00,0xB0,0x00,0x90,0x00,0x90,0x00,0x09,0x00,0x09,0x00,0x98,0x00,0x98,0x00,0x00,0x01,0x00,0x01,0xB5,0x00,0xB5,0x00,0xCA,0x00,0xCA,0x00,0x10, + 0x00,0x10,0x00,0x78,0x00,0x78,0x00,0x7F,0x00,0x7F,0x00,0x26,0x00,0x26,0x00,0x47,0x00,0x47,0x00,0x46,0x00,0x46,0x00,0x45,0x00,0x64,0x1C,0x00,0x97,0x00,0xEC,0x00, + 0xB0,0x00,0x90,0x00,0x90,0x00,0x09,0x00,0x09,0x00,0x98,0x00,0x98,0x00,0x00,0x01,0x00,0x01,0xB5,0x00,0xB5,0x00,0xCA,0x00,0xCA,0x00,0x10,0x00,0x10,0x00,0x78,0x00, + 0x78,0x00,0x7F,0x00,0x7F,0x00,0x26,0x00,0x26,0x00,0x47,0x00,0x47,0x00,0x46,0x00,0x46,0x00,0x45,0x00,0x65,0x20,0x00,0xCA,0x00,0x02,0x01,0x02,0x01,0x9E,0x00,0x9E, + 0x00,0x05,0x01,0x05,0x01,0x90,0x00,0x90,0x00,0x09,0x00,0x09,0x00,0x98,0x00,0x98,0x00,0x00,0x01,0x00,0x01,0xB5,0x00,0xB5,0x00,0xCA,0x00,0xCA,0x00,0x10,0x00,0x10, + 0x00,0x78,0x00,0x78,0x00,0x7F,0x00,0x7F,0x00,0x26,0x00,0x26,0x00,0x47,0x00,0x47,0x00,0x46,0x00,0x46,0x00,0x45,0x00,0x66,0x0A,0x00,0x08,0x00,0x7C,0x00,0x7C,0x00, + 0x67,0x00,0x67,0x00,0x06,0x01,0x06,0x01,0x07,0x01,0x07,0x00,0x01,0x01,0x67,0x26,0x00,0xAC,0x00,0x08,0x01,0x08,0x01,0x09,0x01,0x09,0x01,0x0A,0x01,0x0A,0x01,0x0B, + 0x01,0x0B,0x01,0x0C,0x01,0x0C,0x01,0x0D,0x01,0xB0,0x00,0x90,0x00,0x90,0x00,0x09,0x00,0x09,0x00,0x98,0x00,0x98,0x00,0x00,0x01,0x00,0x01,0xB5,0x00,0xB5,0x00,0xCA, + 0x00,0xCA,0x00,0x10,0x00,0x10,0x00,0x78,0x00,0x78,0x00,0x7F,0x00,0x7F,0x00,0x26,0x00,0x26,0x00,0x47,0x00,0x47,0x00,0x46,0x00,0x46,0x00,0x45,0x00,0x68,0x0E,0x00, + 0x06,0x00,0x29,0x00,0xF3,0x00,0x00,0x01,0x00,0x01,0x98,0x00,0x98,0x00,0x09,0x00,0x09,0x00,0x90,0x00,0x90,0x00,0x0E,0x01,0x0E,0x01,0x0F,0x01,0x69,0x0A,0x00,0x06, + 0x00,0x2F,0x00,0x2F,0x00,0x8D,0x00,0x8D,0x00,0x10,0x01,0x10,0x01,0x06,0x00,0x1D,0x00,0x04,0x00,0x6A,0x10,0x00,0xBE,0x00,0x11,0x01,0x11,0x01,0x7C,0x00,0x7C,0x00, + 0x12,0x01,0x12,0x01,0xBE,0x00,0x98,0x00,0x13,0x01,0x13,0x01,0x14,0x01,0x14,0x01,0x15,0x01,0x15,0x01,0x6E,0x00,0x6B,0x06,0x00,0x06,0x00,0x29,0x00,0x4D,0x00,0x49, + 0x00,0x16,0x01,0x0F,0x01,0x6C,0x02,0x00,0x06,0x00,0x29,0x00,0x6D,0x1A,0x00,0x07,0x00,0x29,0x00,0xF3,0x00,0x00,0x01,0x00,0x01,0x98,0x00,0x98,0x00,0x09,0x00,0x09, + 0x00,0x90,0x00,0x90,0x00,0x0E,0x01,0x0E,0x01,0x0F,0x01,0x0E,0x01,0xE2,0x00,0xE2,0x00,0x17,0x01,0x17,0x01,0x41,0x00,0x41,0x00,0x18,0x01,0x18,0x01,0x19,0x01,0x19, + 0x01,0x1A,0x01,0x6E,0x0E,0x00,0x07,0x00,0x29,0x00,0xF3,0x00,0x00,0x01,0x00,0x01,0x98,0x00,0x98,0x00,0x09,0x00,0x09,0x00,0x90,0x00,0x90,0x00,0x0E,0x01,0x0E,0x01, + 0x0F,0x01,0x6F,0x20,0x00,0x98,0x00,0x00,0x01,0x00,0x01,0xB5,0x00,0xB5,0x00,0xCA,0x00,0xCA,0x00,0x10,0x00,0x10,0x00,0x78,0x00,0x78,0x00,0x7F,0x00,0x7F,0x00,0x26, + 0x00,0x26,0x00,0x47,0x00,0x47,0x00,0x46,0x00,0x46,0x00,0x45,0x00,0x45,0x00,0x9C,0x00,0x9C,0x00,0x22,0x00,0x22,0x00,0xB0,0x00,0xB0,0x00,0x90,0x00,0x90,0x00,0x09, + 0x00,0x09,0x00,0x98,0x00,0x70,0x1C,0x00,0x07,0x00,0x6E,0x00,0x61,0x00,0x1E,0x00,0x1E,0x00,0x2D,0x00,0x2D,0x00,0x01,0x01,0x01,0x01,0x4C,0x00,0x4C,0x00,0xA5,0x00, + 0xA5,0x00,0x02,0x01,0x02,0x01,0x36,0x00,0x36,0x00,0x03,0x01,0x03,0x01,0x04,0x01,0x04,0x01,0x9B,0x00,0x9B,0x00,0x48,0x00,0x48,0x00,0x05,0x00,0x05,0x00,0x27,0x00, + 0x71,0x1C,0x00,0xAC,0x00,0x1B,0x01,0xB0,0x00,0x90,0x00,0x90,0x00,0x09,0x00,0x09,0x00,0x98,0x00,0x98,0x00,0x00,0x01,0x00,0x01,0xB5,0x00,0xB5,0x00,0xCA,0x00,0xCA, + 0x00,0x10,0x00,0x10,0x00,0x78,0x00,0x78,0x00,0x7F,0x00,0x7F,0x00,0x26,0x00,0x26,0x00,0x47,0x00,0x47,0x00,0x46,0x00,0x46,0x00,0x45,0x00,0x72,0x0A,0x00,0x07,0x00, + 0x29,0x00,0xCA,0x00,0xB5,0x00,0xB5,0x00,0x00,0x01,0x00,0x01,0x98,0x00,0x98,0x00,0x09,0x00,0x73,0x20,0x00,0xA5,0x00,0x90,0x00,0x90,0x00,0x01,0x01,0x01,0x01,0x2D, + 0x00,0x2D,0x00,0xFF,0x00,0xFF,0x00,0x61,0x00,0x61,0x00,0xA9,0x00,0xA9,0x00,0x1C,0x01,0x1C,0x01,0x1D,0x01,0x1D,0x01,0x72,0x00,0x72,0x00,0x37,0x00,0x37,0x00,0x03, + 0x01,0x03,0x01,0x46,0x00,0x46,0x00,0x9B,0x00,0x9B,0x00,0x48,0x00,0x48,0x00,0x1E,0x01,0x1E,0x01,0x27,0x00,0x74,0x0A,0x00,0x30,0x00,0x1F,0x01,0x1F,0x01,0xE0,0x00, + 0xE0,0x00,0x80,0x00,0x80,0x00,0x47,0x00,0x07,0x00,0x01,0x01,0x75,0x0E,0x00,0x07,0x00,0x49,0x00,0x49,0x00,0x1E,0x01,0x1E,0x01,0x07,0x01,0x07,0x01,0x80,0x00,0x80, + 0x00,0xE9,0x00,0xE9,0x00,0x37,0x00,0x20,0x01,0x0F,0x01,0x76,0x04,0x00,0x07,0x00,0x80,0x00,0xAC,0x00,0x80,0x00,0x77,0x08,0x00,0x07,0x00,0x48,0x00,0x09,0x00,0x48, + 0x00,0x09,0x00,0xEC,0x00,0x17,0x01,0xEC,0x00,0x78,0x04,0x00,0x07,0x00,0x0F,0x01,0x20,0x01,0x29,0x00,0x79,0x0C,0x00,0x1D,0x00,0x9B,0x00,0xAF,0x00,0x9B,0x00,0x9B, + 0x00,0x13,0x00,0x13,0x00,0x0D,0x01,0x0D,0x01,0x0B,0x00,0x0B,0x00,0x6E,0x00,0x7A,0x06,0x00,0x20,0x01,0x29,0x00,0x07,0x00,0x20,0x01,0x29,0x00,0x0F,0x01,0x7B,0x34, + 0x00,0x12,0x00,0x21,0x01,0x21,0x01,0x66,0x00,0x66,0x00,0x00,0x00,0x00,0x00,0x59,0x00,0x59,0x00,0x22,0x01,0x22,0x01,0x23,0x01,0x23,0x01,0x2D,0x00,0x2D,0x00,0x1F, + 0x00,0x1F,0x00,0x24,0x01,0x21,0x01,0x25,0x01,0x25,0x01,0x1A,0x00,0x1A,0x00,0x26,0x01,0x26,0x01,0x27,0x01,0x27,0x01,0x6F,0x00,0x6F,0x00,0x28,0x01,0x28,0x01,0x29, + 0x01,0x29,0x01,0x75,0x00,0x75,0x00,0x2A,0x01,0x2A,0x01,0x2B,0x01,0x2B,0x01,0x70,0x00,0x70,0x00,0xE0,0x00,0xE0,0x00,0x07,0x01,0x07,0x01,0x2C,0x01,0x2C,0x01,0x2D, + 0x01,0x2D,0x01,0x0D,0x01,0x2E,0x01,0x2F,0x01,0x7C,0x02,0x00,0x65,0x00,0x6E,0x00,0x7D,0x34,0x00,0x65,0x00,0x30,0x01,0x30,0x01,0x31,0x01,0x31,0x01,0xBE,0x00,0xBE, + 0x00,0x32,0x01,0x32,0x01,0x06,0x01,0x06,0x01,0xFD,0x00,0xFD,0x00,0x1D,0x00,0x1D,0x00,0x0E,0x00,0x0E,0x00,0x33,0x01,0x30,0x01,0x34,0x01,0x34,0x01,0x60,0x00,0x60, + 0x00,0x5B,0x00,0x5B,0x00,0x7D,0x00,0x7D,0x00,0x5D,0x00,0x5D,0x00,0xDE,0x00,0xDE,0x00,0xB5,0x00,0xB5,0x00,0x35,0x01,0x35,0x01,0x01,0x00,0x01,0x00,0xEA,0x00,0xEA, + 0x00,0x27,0x00,0x27,0x00,0x1E,0x01,0x1E,0x01,0x36,0x01,0x36,0x01,0x63,0x00,0x63,0x00,0x37,0x01,0x37,0x01,0x38,0x01,0x1C,0x01,0xCB,0x00,0x7E,0x28,0x00,0x10,0x00, + 0xCA,0x00,0xCA,0x00,0xB5,0x00,0xB5,0x00,0x9F,0x00,0x9F,0x00,0xEB,0x00,0xEB,0x00,0x69,0x00,0x69,0x00,0x39,0x01,0x39,0x01,0x9D,0x00,0x9D,0x00,0x95,0x00,0x95,0x00, + 0x3A,0x01,0x3A,0x01,0x3B,0x01,0xCA,0x00,0xA0,0x00,0xA0,0x00,0xAA,0x00,0xAA,0x00,0x3C,0x01,0x3C,0x01,0x3D,0x01,0x3D,0x01,0x3E,0x01,0x3E,0x01,0x9C,0x00,0x9C,0x00, + 0x3F,0x01,0x3F,0x01,0x40,0x01,0x40,0x01,0x3B,0x01,0x3B,0x01,0xBB,0x00 +}; + +static bool isFirst=true; +static bool isBigEndian() { int i = 1; return *(reinterpret_cast<char*>(&i))==0; } + +inline void Swap2Bytes(char* data) +{ + char one_byte; + one_byte = data[0]; data[0] = data[1]; data[1] = one_byte; +} + +inline void Swap4Bytes(char* data) +{ + char one_byte; + one_byte = data[0]; data[0] = data[3]; data[3] = one_byte; + one_byte = data[1]; data[1] = data[2]; data[2] = one_byte; +} + +inline void Swap8Bytes(char* data) +{ + char one_byte; + one_byte = data[0]; data[0] = data[7]; data[7] = one_byte; + one_byte = data[1]; data[1] = data[6]; data[6] = one_byte; + one_byte = data[2]; data[2] = data[5]; data[5] = one_byte; + one_byte = data[3]; data[3] = data[4]; data[4] = one_byte; +} + +static inline uint8_t * getUShort(uint8_t *data,unsigned short &v) +{ + unsigned short *src = reinterpret_cast<unsigned short *>(data); + if ( isBigEndian() && isFirst ) + { + Swap2Bytes(reinterpret_cast<char *>(data)); + } + v = src[0]; + data+=sizeof(unsigned short); + return data; +} + +static inline uint8_t * getUint(uint8_t *data,uint32_t &v) +{ + uint32_t *src = reinterpret_cast<uint32_t *>(data); + if ( isBigEndian() && isFirst ) + { + Swap4Bytes(reinterpret_cast<char *>(data)); + } + v = src[0]; + data+=sizeof(uint32_t); + return data; +} + +class FontChar +{ +public: + FontChar(void) + { + mIndexCount = 0; + mIndices = 0; + mX1 = mY1 = mX2 = mY2 = 0; + } + + uint8_t * init(uint8_t *data,const float *vertices) + { + data = getUShort(data,mIndexCount); + mIndices = reinterpret_cast<unsigned short *>(data); + + if ( isBigEndian() && isFirst ) + { + for (uint16_t i=0; i<mIndexCount; i++) + { + Swap2Bytes(reinterpret_cast<char *>(&mIndices[i])); + } + } + + data+=(mIndexCount*sizeof(unsigned short)); + for (uint32_t i=0; i<mIndexCount; i++) + { + uint32_t index = mIndices[i]; + const float *vertex = &vertices[index*2]; + + if ( i == 0 ) + { + mX1 = mX2 = vertex[0]; + mY1 = mY2 = vertex[1]; + } + else + { + if ( vertex[0] < mX1 ) mX1 = vertex[0]; + if ( vertex[1] < mY1 ) mY1 = vertex[1]; + + if ( vertex[0] > mX2 ) mX2 = vertex[0]; + if ( vertex[1] > mY2 ) mY2 = vertex[1]; + + } + } + + return data; + } + + void vputc(const float *vertices,ProcessRenderDebugHelper *debug,float textScale,float &x,float &y) + { + if ( mIndices ) + { + uint32_t lineCount = uint32_t(mIndexCount/2); + float spacing = (mX2-mX1)+0.05f; + for (uint32_t i=0; i<lineCount; i++) + { + unsigned short i1 = mIndices[i*2+0]; + unsigned short i2 = mIndices[i*2+1]; + + const float *v1 = &vertices[i1*2]; + const float *v2 = &vertices[i2*2]; + + physx::PxVec3 p1(v1[0]+x,v1[1]+y,0); + physx::PxVec3 p2(v2[0]+x,v2[1]+y,0); + p1*=textScale; + p2*=textScale; + + debug->indirectDebugLine(p1,p2); + + } + x+=spacing; + } + else + { + x+=0.1f; + } + } + + float getWidth(void) const + { + float ret = 0.1f; + if ( mIndexCount > 0 ) + { + ret = (mX2-mX1)+0.05f; + } + return ret; + } + + + float mX1; + float mX2; + float mY1; + float mY2; + unsigned short mIndexCount; + unsigned short *mIndices; +}; + + +#define FONT_VERSION 1 + +class MyVectorFont : public physx::shdfnd::UserAllocated +{ +public: + MyVectorFont(void) + { + mVersion = 0; + mVcount = 0; + mCount = 0; + mVertices = 0; + initFont(g_font); + } + + virtual ~MyVectorFont(void) + { + release(); + } + + void release(void) + { + mVersion = 0; + mVcount = 0; + mCount = 0; + mVertices = 0; + } + + void initFont(uint8_t *font) + { + release(); + if ( font[0] == 'F' && font[1] == 'O' && font[2] == 'N' && font[3] == 'T' ) + { + font+=4; + font = getUint(font,mVersion); + if ( mVersion == FONT_VERSION ) + { + font = getUint(font,mVcount); + font = getUint(font,mCount); + font = getUint(font,mIcount); + uint32_t vsize = sizeof(float)*mVcount*2; + mVertices = reinterpret_cast<float *>(font); + if ( isBigEndian() && isFirst ) + { + for (uint32_t i=0; i<(mVcount*2); i++) + { + Swap4Bytes(reinterpret_cast<char *>(&mVertices[i])); + } + } + font+=vsize; + for (uint32_t i=0; i<mCount; i++) + { + uint8_t c = *font++; + font = mCharacters[c].init(font,mVertices); + } + } + isFirst = false; + } + } + + void vprint(const char *buffer,ProcessRenderDebugHelper *debug,float textScale,bool centered) + { + const char *scan = buffer; + float x = 0; + float y = 0; + if ( centered ) + { + float wid=0; + while ( *scan ) + { + unsigned c = unsigned(*scan++); + wid+=mCharacters[c].getWidth(); + } + x = -wid*0.5f; + scan = buffer; + } + while ( *scan ) + { + unsigned c = unsigned(*scan++); + mCharacters[c].vputc(mVertices,debug,textScale,x,y); + } + } + +private: + uint32_t mVersion; + uint32_t mVcount; + uint32_t mCount; + float *mVertices; + uint32_t mIcount; + FontChar mCharacters[256]; +}; + + + + +class ProcessRenderDebugImpl : public ProcessRenderDebug, public physx::shdfnd::UserAllocated, public ProcessRenderDebugHelper +{ +public: + + ProcessRenderDebugImpl(void) + { + mViewMatrix = physx::PxMat44(physx::PxIdentity); + mLines = NULL; + mLineVertexCount = 0; + mMaxLineVertexCount = 0; + mTriangles = NULL; + mSolidVertexCount = 0; + mMaxSolidVertexCount = 0; + } + + virtual ~ProcessRenderDebugImpl(void) + { + PX_FREE(mLines); + PX_FREE(mTriangles); + } + + void flushLines(void) + { + if (mLines != NULL && mInterface != NULL && mLineVertexCount > 0) + { + mInterface->debugRenderLines(mLineVertexCount/2,mLines,mDisplayType!=WORLD_SPACE_NOZ,mDisplayType==SCREEN_SPACE); + } + if (mLines == NULL) + { + mLines = static_cast<RENDER_DEBUG::RenderDebugVertex *>(PX_ALLOC(sizeof(RENDER_DEBUG::RenderDebugVertex)*MAX_LINE_VERTEX, PX_DEBUG_EXP("RenderDebugVertex"))); + mMaxLineVertexCount = MAX_LINE_VERTEX; + } + mLineVertexCount = 0; + } + + void flushTriangles(void) + { + if (mTriangles != NULL && mInterface != NULL && mSolidVertexCount > 0) + { + mInterface->debugRenderTriangles(mSolidVertexCount/3,mTriangles,mDisplayType!=WORLD_SPACE_NOZ,mDisplayType==SCREEN_SPACE); + } + if (mTriangles == NULL) + { + mTriangles = static_cast<RENDER_DEBUG::RenderDebugSolidVertex *>(PX_ALLOC(sizeof(RENDER_DEBUG::RenderDebugSolidVertex)*MAX_SOLID_VERTEX, PX_DEBUG_EXP("RENDER_DEBUG::RenderDebugSolidVertex"))); + mMaxSolidVertexCount = MAX_SOLID_VERTEX; + } + mSolidVertexCount = 0; + } + + virtual void flush(RENDER_DEBUG::RenderDebugInterface *iface,DisplayType type) + { + mInterface = iface; + mDisplayType = type; + flushLines(); + flushTriangles(); + new ( &mCurrentState ) RenderState; // reset renderstate to inifial conditions. + } + + bool isIdentity(const physx::PxMat44 &t) const + { + physx::PxMat44 id = physx::PxMat44(physx::PxIdentity); + const float *f1 = t.front(); + const float *f2 = id.front(); + for (uint32_t i=0; i<16; i++) + { + float diff = physx::PxAbs( f1[i] - f2[i] ); + if ( diff > 0.000001f ) + return false; + } + return true; + } + + virtual void processRenderDebug(const DebugPrimitive **plist,uint32_t pcount,RENDER_DEBUG::RenderDebugInterface *iface,DisplayType type) + { + mInterface = iface; + mDisplayType = type; + + for (uint32_t i=0; i<pcount; i++) + { + const DebugPrimitive &p = *plist[i]; + switch ( p.mCommand ) + { + case DebugCommand::DEBUG_RELEASE_TRIANGLE_MESH: + if ( iface ) + { + const DebugReleaseTriangleMesh &d = static_cast< const DebugReleaseTriangleMesh &>(p); + iface->releaseTriangleMesh(d.mMeshId); + } + break; + case DebugCommand::DEBUG_RENDER_TRIANGLE_MESH_INSTANCES: + { + const DebugRenderTriangleMeshInstances &dgs = static_cast< const DebugRenderTriangleMeshInstances &>(p); + debugRenderTriangleMeshInstances(dgs,iface); + } + break; + case DebugCommand::DEBUG_CONVEX_HULL: + { + const DebugConvexHull &dgs = static_cast< const DebugConvexHull &>(p); + debugConvexHull(dgs); + } + break; + case DebugCommand::DEBUG_RENDER_POINTS: + { + const DebugRenderPoints &dgs = static_cast< const DebugRenderPoints &>(p); + debugRenderPoints(dgs,iface); + } + break; + case DebugCommand::DEBUG_RENDER_LINES: + { + const DebugRenderLines &dgs = static_cast< const DebugRenderLines &>(p); + debugRenderLines(dgs,iface); + } + break; + case DebugCommand::DEBUG_RENDER_TRIANGLES: + { + const DebugRenderTriangles &dgs = static_cast< const DebugRenderTriangles &>(p); + debugRenderTriangles(dgs,iface); + } + break; + case DebugCommand::DEBUG_UNREGISTER_INPUT_EVENT: + if ( iface ) + { + const DebugUnregisterInputEvent &d = static_cast< const DebugUnregisterInputEvent &>(p); + iface->unregisterInputEvent(static_cast<InputEventIds::Enum>(d.mEventId)); + } + break; + case DebugCommand::DEBUG_REGISTER_INPUT_EVENT: + if ( iface ) + { + const DebugRegisterInputEvent &d = static_cast< const DebugRegisterInputEvent &>(p); + if ( d.mDigital ) + { + iface->registerDigitalInputEvent(static_cast<InputEventIds::Enum>(d.mEventId), static_cast<InputIds::Enum>(d.mInputId)); + } + else + { + iface->registerAnalogInputEvent(static_cast<InputEventIds::Enum>(d.mEventId), d.mSensitivity, static_cast<InputIds::Enum>(d.mInputId)); + } + } + break; + case DebugCommand::DEBUG_SKIP_FRAME: + break; + case DebugCommand::DEBUG_RESET_INPUT_EVENTS: + if ( iface ) + { + iface->resetInputEvents(); + } + break; + case DebugCommand::DEBUG_CREATE_TRIANGLE_MESH: + { + const DebugCreateTriangleMesh &dgs = static_cast< const DebugCreateTriangleMesh &>(p); + debugCreateTriangleMesh(dgs,iface); + } + break; + case DebugCommand::DEBUG_REFRESH_TRIANGLE_MESH_VERTICES: + { + const DebugRefreshTriangleMeshVertices &dgs = static_cast< const DebugRefreshTriangleMeshVertices &>(p); + debugRefreshTriangleMeshVertices(dgs,iface); + } + break; + case DebugCommand::DEBUG_GRAPH: + { + const DebugGraphStream &dgs = static_cast< const DebugGraphStream &>(p); + debugGraph(dgs); + } + break; + case DebugCommand::DEBUG_GRADIENT_TRI: + { + const DebugGradientTri &dg = static_cast< const DebugGradientTri &>(p); + debugGradientTri(dg); + if ( iface ) + { + RenderDebugSolidVertex verts[3]; + verts[0].mPos[0] = dg.mP1.x; verts[0].mPos[1] = dg.mP1.y; verts[0].mPos[2] = dg.mP1.z; + verts[1].mPos[0] = dg.mP2.x; verts[1].mPos[1] = dg.mP2.y; verts[1].mPos[2] = dg.mP2.z; + verts[2].mPos[0] = dg.mP3.x; verts[2].mPos[1] = dg.mP3.y; verts[2].mPos[2] = dg.mP3.z; + const physx::PxVec3 v1(dg.mP1.x, dg.mP1.y, dg.mP1.z), + v2(dg.mP2.x, dg.mP2.y, dg.mP2.z), + v3(dg.mP3.x, dg.mP3.y, dg.mP3.z); + + const physx::PxVec3 n = physx::PxVec3(v2-v1).cross(physx::PxVec3(v3-v1)).getNormalized(); + verts[0].mNormal[0] = n.x; + verts[0].mNormal[1] = n.y; + verts[0].mNormal[2] = n.z; + verts[1].mNormal[0] = n.x; + verts[1].mNormal[1] = n.y; + verts[1].mNormal[2] = n.z; + verts[2].mNormal[0] = n.x; + verts[2].mNormal[1] = n.y; + verts[2].mNormal[2] = n.z; + iface->debugRenderTriangles(1, verts, false, false); + } + } + break; + case DebugCommand::SET_CURRENT_TRANSFORM: + { + const DebugSetCurrentTransform &dg = static_cast< const DebugSetCurrentTransform &>(p); + if ( isIdentity(dg.mTransform )) + { + mCurrentState.mPose = NULL; + } + else + { + mCurrentState.mCurrentPose = dg.mTransform; + mCurrentState.mPose = &mCurrentState.mCurrentPose; + } + } + break; + case DebugCommand::DEBUG_LINE: + { + const DebugLine &dg = static_cast< const DebugLine &>(p); + debugLine(dg.mP1,dg.mP2,mCurrentState.mColor,mCurrentState.mColor); + } + break; + case DebugCommand::DRAW_GRID: + { + const DrawGrid &dg = static_cast< const DrawGrid &>(p); + drawGrid(dg); + } + break; + case DebugCommand::SET_CURRENT_COLOR: + { + const DebugPrimitiveU32 &dg = static_cast< const DebugPrimitiveU32 &>(p); + mCurrentState.mColor = dg.mValue; + } + break; + case DebugCommand::SET_CURRENT_ARROW_COLOR: + { + const DebugPrimitiveU32 &dg = static_cast< const DebugPrimitiveU32 &>(p); + mCurrentState.mArrowColor = dg.mValue; + } + break; + case DebugCommand::SET_CURRENT_TILE1: + { + const DebugPrimitiveF32 &dg = static_cast< const DebugPrimitiveF32 &>(p); + mCurrentState.mTileRate1 = dg.mValue; + } + break; + case DebugCommand::SET_CURRENT_TILE2: + { + const DebugPrimitiveF32 &dg = static_cast< const DebugPrimitiveF32 &>(p); + mCurrentState.mTileRate2 = dg.mValue; + } + break; + case DebugCommand::SET_CURRENT_TEXTURE1: + { + const DebugPrimitiveU32 &dg = static_cast< const DebugPrimitiveU32 &>(p); + mCurrentState.mTexture1 = dg.mValue; + } + break; + case DebugCommand::SET_CURRENT_TEXTURE2: + { + const DebugPrimitiveU32 &dg = static_cast< const DebugPrimitiveU32 &>(p); + mCurrentState.mTexture2 = dg.mValue; + } + break; + case DebugCommand::SET_CURRENT_USER_ID: + { + const DebugPrimitiveU32 &dg = static_cast< const DebugPrimitiveU32 &>(p); + mCurrentState.mUserId = int32_t(dg.mValue); + } + break; + case DebugCommand::SET_CURRENT_RENDER_SCALE: + { + const DebugPrimitiveF32 &dg = static_cast< const DebugPrimitiveF32 &>(p); + mCurrentState.mRenderScale = dg.mValue; + } + break; + case DebugCommand::SET_CURRENT_ARROW_SIZE: + { + const DebugPrimitiveF32 &dg = static_cast< const DebugPrimitiveF32 &>(p); + mCurrentState.mArrowSize = dg.mValue; + } + break; + case DebugCommand::SET_CURRENT_RENDER_STATE: + { + const DebugPrimitiveU32 &dg = static_cast< const DebugPrimitiveU32 &>(p); + mCurrentState.mStates = dg.mValue; + } + break; + case DebugCommand::SET_CURRENT_TEXT_SCALE: + { + const DebugPrimitiveF32 &dg = static_cast< const DebugPrimitiveF32 &>(p); + mCurrentState.mTextScale = dg.mValue; + } + break; + case DebugCommand::DEBUG_TEXT: + { + const DebugText &dg = static_cast< const DebugText &>(p); + debugText(dg); + } + break; + case DebugCommand::DEBUG_TEXT2D: + if ( iface ) + { + const DebugText2D &dg = static_cast< const DebugText2D &>(p); + iface->debugText2D(dg.mPosition.x,dg.mPosition.y,dg.mScale,dg.mShadowOffset,dg.mForceFixWidthNumbers ? true : false,dg.mTextColor, dg.mText ); + } + break; + case DebugCommand::DEBUG_BOUND: + { + const DebugBound &db = static_cast< const DebugBound &>(p); + debugBound(db); + } + break; + case DebugCommand::DEBUG_QUAD: + { + const DebugQuad &b = static_cast< const DebugQuad &>(p); + debugQuad(b); + } + break; + case DebugCommand::DEBUG_POINT: + { + const DebugPoint &b = static_cast< const DebugPoint &>(p); + debugPoint(b); + } + break; + case DebugCommand::DEBUG_POINT_SCALE: + { + const DebugPointScale &b = static_cast< const DebugPointScale &>(p); + debugPoint(b); + } + break; + case DebugCommand::DEBUG_RECT2D: + { + const DebugRect2d &d = static_cast<const DebugRect2d &>(p); + debugRect2d(d); + } + break; + case DebugCommand::DEBUG_GRADIENT_LINE: + { + const DebugGradientLine &d = static_cast< const DebugGradientLine &>(p); + debugGradientLine(d); + } + break; + case DebugCommand::DEBUG_RAY: + { + const DebugRay &d = static_cast< const DebugRay &>(p); + debugRay(d); + } + break; + case DebugCommand::DEBUG_CYLINDER: + { + const DebugCylinder &d = static_cast< const DebugCylinder &>(p); + debugCylinder(d); + } + break; + case DebugCommand::DEBUG_CIRCLE: + { + const DebugCircle &d = static_cast< const DebugCircle &>(p); + debugCircle(d); + } + break; + case DebugCommand::DEBUG_POINT_CYLINDER: + { + const DebugPointCylinder &d = static_cast< const DebugPointCylinder &>(p); + debugPointCylinder(d); + } + break; + case DebugCommand::DEBUG_THICK_RAY: + { + const DebugThickRay &d = static_cast< const DebugThickRay &>(p); + debugThickRay(d); + } + break; + case DebugCommand::DEBUG_PLANE: + { + const DebugPlane &d = static_cast< const DebugPlane &>(p); + debugPlane(d); + } + break; + case DebugCommand::DEBUG_TRI: + { + const DebugTri &d = static_cast< const DebugTri &>(p); + debugTri(&d.mP1,&d.mP2,&d.mP3,NULL,NULL,NULL,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,false); + } + break; + case DebugCommand::DEBUG_TRI_NORMALS: + { + const DebugTriNormals &d = static_cast< const DebugTriNormals &>(p); + debugTriNormals(d); + } + break; + case DebugCommand::DEBUG_GRADIENT_TRI_NORMALS: + { + const DebugGradientTriNormals &d = static_cast< const DebugGradientTriNormals &>(p); + debugGradientTriNormals(d); + } + break; + case DebugCommand::DEBUG_SPHERE: + { + const DebugSphere &d = static_cast< const DebugSphere &>(p); + debugSphere(d); + } + break; + case DebugCommand::DEBUG_SQUASHED_SPHERE: + { + const DebugSquashedSphere &d = static_cast< const DebugSquashedSphere &>(p); + debugSphere(d); + } + break; + case DebugCommand::DEBUG_CAPSULE: + { + const DebugCapsule &d = static_cast<const DebugCapsule &>(p); + debugCapsule(d); + } + break; + case DebugCommand::DEBUG_CAPSULE_TAPERED: + { + const DebugTaperedCapsule&d = static_cast<const DebugTaperedCapsule&>(p); + debugTaperedCapsule(d); + } + break; + case DebugCommand::DEBUG_AXES: + { + const DebugAxes &d = static_cast< const DebugAxes &>(p); + debugAxes(d); + } + break; + case DebugCommand::DEBUG_ARC: + { + const DebugArc &d = static_cast< const DebugArc &>(p); + debugArc(d); + } + break; + case DebugCommand::DEBUG_THICK_ARC: + { + const DebugThickArc &d = static_cast< const DebugThickArc &>(p); + debugThickArc(d); + } + break; + case DebugCommand::DEBUG_DETAILED_SPHERE: + { + const DebugDetailedSphere &d = static_cast< const DebugDetailedSphere &>(p); + debugDetailedSphere(d); + } + break; + case DebugCommand::DEBUG_MESSAGE: + { + const DebugMessage &d = static_cast< const DebugMessage &>(p); + mInterface->debugMessage(d.mText); + } + break; + case DebugCommand::DEBUG_CREATE_CUSTOM_TEXTURE: + { + const DebugCreateCustomTexture &d = static_cast< const DebugCreateCustomTexture &>(p); + mInterface->createCustomTexture(d.mId,d.mTextureName); + } + break; + case DebugCommand::DEBUG_FRUSTUM: + { + const DebugFrustum &f = static_cast< const DebugFrustum &>(p); + debugFrustum(f.mView,f.mProj); + } + break; + case DebugCommand::DEBUG_CONE: + { + const DebugCone &c = static_cast< const DebugCone &>(p); + debugCone(c); + } + break; + case DebugCommand::DEBUG_BLOCK_INFO: + { + } + break; + case DebugCommand::DEBUG_LAST: + break; + default: + PX_ALWAYS_ASSERT(); + break; + } + } + } + + virtual void release(void) + { + delete this; + } + + PX_INLINE int32_t clampColor(int32_t c) + { + if ( c < 0 ) + { + c = 0; + } + else if ( c > 255 ) + { + c = 255; + } + return c; + } + + void debugText(const DebugText &dg) + { + physx::PxMat44 *savePose = mCurrentState.mPose; + mCurrentState.mPose = NULL; + physx::PxMat44 pose = dg.mPose; + pose.setPosition( pose.getPosition()+dg.mPosition ); + if ( savePose ) + { + pose = *savePose * pose; + } + + if ( mCurrentState.isCameraFacing() ) + { + float *cameraWorldPose = const_cast<float*>(pose.front()); + const float *viewMatrix = mViewMatrix.front(); + cameraWorldPose[0] = viewMatrix[0]; + cameraWorldPose[1] = viewMatrix[4]; + cameraWorldPose[2] = viewMatrix[8]; + cameraWorldPose[3] = 0; + + cameraWorldPose[4] = viewMatrix[1]; + cameraWorldPose[5] = viewMatrix[5]; + cameraWorldPose[6] = viewMatrix[9]; + cameraWorldPose[7] = 0; + + cameraWorldPose[8] = viewMatrix[2]; + cameraWorldPose[9] = viewMatrix[6]; + cameraWorldPose[10] = viewMatrix[10]; + cameraWorldPose[11] = 0; + } + mCurrentState.mPose = &pose; + mVectorFont.vprint(dg.mText, this, mCurrentState.mTextScale, mCurrentState.isCentered() ); + mCurrentState.mPose = savePose; + } + + uint32_t getColor(uint32_t r,uint32_t g,uint32_t b,float percent = 0.0f) + { + uint32_t dr = uint32_t(static_cast<float>(r)*percent); + uint32_t dg = uint32_t(static_cast<float>(g)*percent); + uint32_t db = uint32_t(static_cast<float>(b)*percent); + r-=dr; + g-=dg; + b-=db; + + const uint32_t c = 0xff000000 | (r<<16) | (g<<8) | b; + return c; + } + + + PX_INLINE void swapYZ(physx::PxVec3 &p) + { + float y = p.y; + p.y = p.z; + p.z = y; + } + + void drawGrid(const DrawGrid &dg) + { + bool zup = dg.mZup ? true : false; + uint32_t gridSize = dg.mGridSize; + int32_t GRIDSIZE = int32_t(gridSize); + + uint32_t c1 = getColor(133,153,181,0.1f); + uint32_t c2 = getColor(133,153,181,0.3f); + uint32_t c3 = getColor(133,153,181,0.5f); + + const float TSCALE = 1.0f; + + float BASELOC = 0-0.05f; + + for (int32_t x=-GRIDSIZE; x<=GRIDSIZE; x++) + { + uint32_t c = c1; + if ( (x%10) == 0 ) c = c2; + if ( (x%GRIDSIZE) == 0 ) c = c3; + + physx::PxVec3 p1( static_cast<float>(x), static_cast<float>(-GRIDSIZE), BASELOC ); + physx::PxVec3 p2( static_cast<float>(x), static_cast<float>(+GRIDSIZE), BASELOC ); + + p1*=TSCALE; + p2*=TSCALE; + + if ( !zup ) + { + swapYZ(p1); + swapYZ(p2); + } + debugLine(p1,p2,c,c); + + + } + + for (int32_t y=-GRIDSIZE; y<=GRIDSIZE; y++) + { + uint32_t c = c1; + + if ( (y%10) == 0 ) c = c2; + if ( (y%GRIDSIZE) == 0 ) c = c3; + + physx::PxVec3 p1(static_cast<float>(-GRIDSIZE), static_cast<float>(y), BASELOC); + physx::PxVec3 p2(static_cast<float>(+GRIDSIZE), static_cast<float>(y), BASELOC); + + p1*=TSCALE; + p2*=TSCALE; + + if ( !zup ) + { + swapYZ(p1); + swapYZ(p2); + } + + debugLine(p1,p2,c,c); + } + } + + PX_INLINE void debugLine(const physx::PxVec3 &p1,const physx::PxVec3 &p2,uint32_t color1,uint32_t color2) + { + RENDER_DEBUG::RenderDebugVertex *v = getDebugVertex(2); + + if ( mCurrentState.mPose ) + { + physx::PxVec3 _p1 = mCurrentState.mPose->transform(p1); + physx::PxVec3 _p2 = mCurrentState.mPose->transform(p2); + v[0].mPos[0] = _p1.x*mCurrentState.mRenderScale; + v[0].mPos[1] = _p1.y*mCurrentState.mRenderScale; + v[0].mPos[2] = _p1.z*mCurrentState.mRenderScale; + v[0].mColor = color1; + + v[1].mPos[0] = _p2.x*mCurrentState.mRenderScale; + v[1].mPos[1] = _p2.y*mCurrentState.mRenderScale; + v[1].mPos[2] = _p2.z*mCurrentState.mRenderScale; + v[1].mColor = color2; + } + else + { + v[0].mPos[0] = p1.x*mCurrentState.mRenderScale; + v[0].mPos[1] = p1.y*mCurrentState.mRenderScale; + v[0].mPos[2] = p1.z*mCurrentState.mRenderScale; + v[0].mColor = color1; + + v[1].mPos[0] = p2.x*mCurrentState.mRenderScale; + v[1].mPos[1] = p2.y*mCurrentState.mRenderScale; + v[1].mPos[2] = p2.z*mCurrentState.mRenderScale; + v[1].mColor = color2; + } + } + + PX_INLINE physx::PxVec3 rotate2d(const physx::PxVec3 &p,float r) + { + physx::PxVec3 ret; + ret.x = p.x*cosf(r) - p.y*sinf(r); + ret.y = p.x*sinf(r) + p.y*cosf(r); + ret.z = 0; + return ret; + } + + PX_INLINE physx::PxVec3 facing(const physx::PxVec3 &p,const physx::PxMat44 &inverseViewMatrix) + { + return inverseViewMatrix.rotate(p); + } + + PX_INLINE void debugQuad(const DebugQuad &p) + { + physx::PxVec3 points[4]; + + physx::PxMat44 inverseViewMatrix; + + // get the inverse view matrix + float *cameraWorldPose = const_cast<float *>(inverseViewMatrix.front()); + const float *viewMatrix = mViewMatrix.front(); + cameraWorldPose[0] = viewMatrix[0]; + cameraWorldPose[1] = viewMatrix[4]; + cameraWorldPose[2] = viewMatrix[8]; + cameraWorldPose[3] = 0; + + cameraWorldPose[4] = viewMatrix[1]; + cameraWorldPose[5] = viewMatrix[5]; + cameraWorldPose[6] = viewMatrix[9]; + cameraWorldPose[7] = 0; + + cameraWorldPose[8] = viewMatrix[2]; + cameraWorldPose[9] = viewMatrix[6]; + cameraWorldPose[10] = viewMatrix[10]; + cameraWorldPose[11] = 0; + + // apply scale, rotation, and make the quad face the camera. + points[0] = facing(rotate2d(physx::PxVec3(-p.mScale.x*0.5f,-p.mScale.y*0.5f,0),p.mRotation),inverseViewMatrix)+p.mPos; + points[1] = facing(rotate2d(physx::PxVec3(p.mScale.x*0.5f,-p.mScale.y*0.5f,0),p.mRotation),inverseViewMatrix)+p.mPos; + points[2] = facing(rotate2d(physx::PxVec3(p.mScale.x*0.5f,p.mScale.y*0.5f,0),p.mRotation),inverseViewMatrix)+p.mPos; + points[3] = facing(rotate2d(physx::PxVec3(-p.mScale.x*0.5f,p.mScale.y*0.5f,0),p.mRotation),inverseViewMatrix)+p.mPos; + + + if ( mCurrentState.hasRenderState(RENDER_DEBUG::DebugRenderState::SolidWireShaded) || mCurrentState.hasRenderState(RENDER_DEBUG::DebugRenderState::SolidShaded) ) + { + physx::PxVec3 normal(1.0f,1.0f,0); + uint32_t renderState = mCurrentState.mStates; + mCurrentState.clearRenderState(RENDER_DEBUG::DebugRenderState::SolidWireShaded); + mCurrentState.setRenderState(RENDER_DEBUG::DebugRenderState::SolidShaded); + debugTri(&points[0],&points[1],&points[2],&normal,&normal,&normal); + debugTri(&points[0],&points[2],&points[3],&normal,&normal,&normal); + mCurrentState.mStates = renderState; + } + if ( mCurrentState.hasRenderState(RENDER_DEBUG::DebugRenderState::SolidWireShaded) || !mCurrentState.hasRenderState(RENDER_DEBUG::DebugRenderState::SolidShaded) ) + { + uint32_t currentColor = mCurrentState.mColor; + if ( mCurrentState.hasRenderState(RENDER_DEBUG::DebugRenderState::SolidWireShaded)) + { + mCurrentState.mColor = mCurrentState.mArrowColor; + } + debugLine(points[0], points[1] ); + debugLine(points[1], points[2] ); + debugLine(points[2], points[3] ); + debugLine(points[3], points[0] ); + mCurrentState.mColor = currentColor; + } + } + + + PX_INLINE void debugPoint(const DebugPoint &p) + { + const physx::PxVec3 *source = debug_point; + + for (int32_t i=0; i<3; i++) + { + physx::PxVec3 p1 = source[0]*p.mSize+p.mPos; + physx::PxVec3 p2 = source[1]*p.mSize+p.mPos; + source+=2; + + debugLine(p1,p2); + } + } + + PX_INLINE void debugPoint(const DebugPointScale &p) + { + const physx::PxVec3 *source = debug_point; + + for (uint32_t i=0; i<3; i++) + { + physx::PxVec3 p1 = source[0]*p.mSize[i]+p.mPos; + physx::PxVec3 p2 = source[1]*p.mSize[i]+p.mPos; + source+=2; + debugLine(p1,p2); + } + } + + + PX_INLINE void debugGradientTri(const DebugGradientTri &tri) + { + debugTri(&tri.mP1,&tri.mP2,&tri.mP3,NULL,NULL,NULL,tri.mC1,tri.mC2,tri.mC3,true); + } + + PX_INLINE void debugLine(const physx::PxVec3 &p1,const physx::PxVec3 &p2) + { + debugLine(p1,p2,mCurrentState.mColor,mCurrentState.mColor); + } + + virtual void indirectDebugLine(const physx::PxVec3 &p1,const physx::PxVec3 &p2) + { + debugLine(p1,p2,mCurrentState.mColor,mCurrentState.mColor); + } + + RENDER_DEBUG::RenderDebugVertex * getDebugVertex(uint32_t count) + { + if (( mLineVertexCount+count) > mMaxLineVertexCount ) + { + flushLines(); + } + PX_ASSERT( count < mMaxLineVertexCount ); + RENDER_DEBUG::RenderDebugVertex *ret = &mLines[mLineVertexCount]; + mLineVertexCount+=count; + return ret; + } + + RENDER_DEBUG::RenderDebugSolidVertex * getDebugSolidVertex(uint32_t count) + { + if (( mSolidVertexCount+count) > mMaxSolidVertexCount ) + { + flushTriangles(); + } + PX_ASSERT( count < mMaxSolidVertexCount ); + RENDER_DEBUG::RenderDebugSolidVertex *ret = &mTriangles[mSolidVertexCount]; + mSolidVertexCount+=count; + return ret; + } + + virtual void flushFrame(RENDER_DEBUG::RenderDebugInterface * /*iface*/) + { + } + + PX_INLINE void debugBound(const DebugBound &b) + { + physx::PxVec3 box[8]; + box[0] = physx::PxVec3( b.mBmin.x, b.mBmin.y, b.mBmin.z ); + box[1] = physx::PxVec3( b.mBmax.x, b.mBmin.y, b.mBmin.z ); + box[2] = physx::PxVec3( b.mBmax.x, b.mBmax.y, b.mBmin.z ); + box[3] = physx::PxVec3( b.mBmin.x, b.mBmax.y, b.mBmin.z ); + box[4] = physx::PxVec3( b.mBmin.x, b.mBmin.y, b.mBmax.z ); + box[5] = physx::PxVec3( b.mBmax.x, b.mBmin.y, b.mBmax.z ); + box[6] = physx::PxVec3( b.mBmax.x, b.mBmax.y, b.mBmax.z ); + box[7] = physx::PxVec3( b.mBmin.x, b.mBmax.y, b.mBmax.z ); + debugBound(box); + } + + float computePlaneEquation(const physx::PxVec3 &A,const physx::PxVec3 &B,const physx::PxVec3 &C,physx::PxVec3 &normal) + { + physx::PxVec3 v = B - C; + physx::PxVec3 w = A - B; + + physx::PxVec3 vw; + + vw.x = v.y * w.z - v.z * w.y; + vw.y = v.z * w.x - v.x * w.z; + vw.z = v.x * w.y - v.y * w.x; + + float mag = vw.magnitude(); + + if ( mag < 0.000001f ) + { + mag = 0; + } + else + { + mag = 1.0f/mag; + } + + normal = vw*mag; + + float D = 0.0f - ((normal.x*A.x)+(normal.y*A.y)+(normal.z*A.z)); + + return D; + } + + void debugTri(const physx::PxVec3 *_v1,const physx::PxVec3 *_v2,const physx::PxVec3 *_v3,const physx::PxVec3 *_n1=NULL,const physx::PxVec3 *_n2=NULL,const physx::PxVec3 *_n3=NULL,uint32_t c1=0xFFFFFFFF,uint32_t c2=0xFFFFFFFF,uint32_t c3=0xFFFFFFFF,bool useGradientColors=false) + { + if( mCurrentState.hasRenderState(RENDER_DEBUG::DebugRenderState::DoubleSided) ) + { + debugTriOneSide(_v1, _v2, _v3, _n1, _n2, _n3, c1, c2, c3, useGradientColors, false); + debugTriOneSide(_v1, _v2, _v3, _n1, _n2, _n3, c1, c2, c3, useGradientColors, true); + } + else + { + debugTriOneSide(_v1, _v2, _v3, _n1, _n2, _n3, c1, c2, c3, useGradientColors, mCurrentState.hasRenderState(RENDER_DEBUG::DebugRenderState::CounterClockwise)); + } + } + + void debugTriOneSide(const physx::PxVec3 *_v1, + const physx::PxVec3 *_v2, + const physx::PxVec3 *_v3, + const physx::PxVec3 *_n1=NULL, + const physx::PxVec3 *_n2=NULL, + const physx::PxVec3 *_n3=NULL, + uint32_t c1=0xFFFFFFFF, + uint32_t c2=0xFFFFFFFF, + uint32_t c3=0xFFFFFFFF, + bool useGradientColors=false, + bool counterClockwise=false) + { + if (counterClockwise) + { + const physx::PxVec3 *temp = _v1; + _v1 = _v3; + _v3 = temp; + if ( _n1 ) + { + temp = _n1; + _n1 = _n3; + _n3 = temp; + } + // switch colors too + { + uint32_t t = c1; + c1 = c3; + c3 = t; + } + } + + if ( !useGradientColors ) + { + c1 = mCurrentState.mColor; + c2 = mCurrentState.mColor; + c3 = mCurrentState.mColor; + } + + physx::PxVec3 v1 = *_v1; + physx::PxVec3 v2 = *_v2; + physx::PxVec3 v3 = *_v3; + + if (mCurrentState.mPose) + { + v1 = mCurrentState.mPose->transform(*_v1); + v2 = mCurrentState.mPose->transform(*_v2); + v3 = mCurrentState.mPose->transform(*_v3); + } + + v1 *= mCurrentState.mRenderScale; + v2 *= mCurrentState.mRenderScale; + v3 *= mCurrentState.mRenderScale; + + if (mCurrentState.isSolid()) + { + RENDER_DEBUG::RenderDebugSolidVertex* verts = getDebugSolidVertex(3); + + physx::PxVec3 n1, n2, n3; + if (_n1 == NULL) + { + computePlaneEquation(v3, v2, v1, n1); + if (counterClockwise) + { + n1 = -n1; + } + n2 = n1; + n3 = n1; + } + else + { + if (mCurrentState.mPose) + { + n1 = mCurrentState.mPose->rotate(*_n1); + n2 = mCurrentState.mPose->rotate(*_n2); + n3 = mCurrentState.mPose->rotate(*_n3); + } + else + { + n1 = *_n1; + n2 = *_n2; + n3 = *_n3; + } + } + + verts[0].mPos[0] = v1.x; + verts[0].mPos[1] = v1.y; + verts[0].mPos[2] = v1.z; + verts[0].mColor = c1; + verts[0].mNormal[0] = n1.x; + verts[0].mNormal[1] = n1.y; + verts[0].mNormal[2] = n1.z; + + verts[1].mPos[0] = v2.x; + verts[1].mPos[1] = v2.y; + verts[1].mPos[2] = v2.z; + verts[1].mColor = c2; + verts[1].mNormal[0] = n2.x; + verts[1].mNormal[1] = n2.y; + verts[1].mNormal[2] = n2.z; + + verts[2].mPos[0] = v3.x; + verts[2].mPos[1] = v3.y; + verts[2].mPos[2] = v3.z; + verts[2].mColor = c3; + verts[2].mNormal[0] = n3.x; + verts[2].mNormal[1] = n3.y; + verts[2].mNormal[2] = n3.z; + } + + if ( !mCurrentState.hasRenderState(RENDER_DEBUG::DebugRenderState::SolidShaded) || mCurrentState.hasRenderState(RENDER_DEBUG::DebugRenderState::SolidWireShaded) ) + { + if ( mCurrentState.hasRenderState(RENDER_DEBUG::DebugRenderState::SolidWireShaded) ) + { + c1 = c2 = c3 = mCurrentState.mArrowColor; + } + RENDER_DEBUG::RenderDebugVertex *lines = getDebugVertex(6); + // first vertex (start of first segment, end of third) + lines[0].mPos[0] = lines[5].mPos[0] = v1.x; + lines[0].mPos[1] = lines[5].mPos[1] = v1.y; + lines[0].mPos[2] = lines[5].mPos[2] = v1.z; + lines[0].mColor = lines[5].mColor = c1; + + // second vertex (end of first segment, start of second) + lines[1].mPos[0] = lines[2].mPos[0] = v2.x; + lines[1].mPos[1] = lines[2].mPos[1] = v2.y; + lines[1].mPos[2] = lines[2].mPos[2] = v2.z; + lines[1].mColor = lines[2].mColor = c2; + + // third vertex (end of second segment, start of third) + lines[3].mPos[0] = lines[4].mPos[0] = v3.x; + lines[3].mPos[1] = lines[4].mPos[1] = v3.y; + lines[3].mPos[2] = lines[4].mPos[2] = v3.z; + lines[3].mColor = lines[4].mColor = c3; + } + } + + + PX_INLINE void debugBound(const physx::PxVec3 *box) + { + if ( mCurrentState.isSolid() ) + { + debugTri(&box[2],&box[1],&box[0]); + debugTri(&box[3],&box[2],&box[0]); + + debugTri(&box[7],&box[2],&box[3]); + debugTri(&box[7],&box[6],&box[2]); + + debugTri(&box[5],&box[1],&box[2]); + debugTri(&box[5],&box[2],&box[6]); + + debugTri(&box[5],&box[4],&box[1]); + debugTri(&box[4],&box[0],&box[1]); + + debugTri(&box[4],&box[6],&box[7]); + debugTri(&box[4],&box[5],&box[6]); + + debugTri(&box[4],&box[7],&box[0]); + debugTri(&box[7],&box[3],&box[0]); + } + else + { + debugLine(box[0], box[1]); + debugLine(box[1], box[2]); + debugLine(box[2], box[3]); + debugLine(box[3], box[0]); + + debugLine(box[4], box[5]); + debugLine(box[5], box[6]); + debugLine(box[6], box[7]); + debugLine(box[7], box[4]); + + debugLine(box[0], box[4]); + debugLine(box[1], box[5]); + debugLine(box[2], box[6]); + debugLine(box[3], box[7]); + } + } + + + PX_INLINE void debugRect2d(const DebugRect2d &d) + { + physx::PxVec3 points[4]; + points[0] = physx::PxVec3(d.mX1,d.mY1,0.0f); + points[1] = physx::PxVec3(d.mX2,d.mY1,0.0f); + points[2] = physx::PxVec3(d.mX2,d.mY2,0.0f); + points[3] = physx::PxVec3(d.mX1,d.mY2,0.0f); + debugPolygon(4,points); + } + + PX_INLINE void debugGradientLine(const DebugGradientLine &d) + { + debugLine(d.mP1,d.mP2,d.mC1,d.mC2); + } + + PX_INLINE void debugRay(const DebugRay &d) + { + debugLine(d.mP1,d.mP2); + physx::PxVec3 dir = d.mP2 - d.mP1; + float mag = dir.normalize(); + float arrowSize = mCurrentState.mArrowSize; + if ( arrowSize > (mag*0.2f )) + { + arrowSize = mag*0.2f; + } + physx::PxVec3 ref(0,1.0f,0); + physx::PxQuat quat; + rotationArc(ref,dir,quat); + physx::PxMat44 matrix(quat); + matrix.setPosition(d.mP2); + + uint32_t pcount = 0; + physx::PxVec3 points[24]; + physx::PxVec3 *dest = points; + + for (float a=30; a<=360; a+=30) + { + float r = a*FM_DEG_TO_RAD; + float x = physx::PxCos(r)*arrowSize; + float y = physx::PxSin(r)*arrowSize; + + dest->x = x; + dest->y = -3*arrowSize; + dest->z = y; + dest++; + pcount++; + } + + physx::PxVec3 *prev = &points[(pcount-1)]; + physx::PxVec3 *p = points; + physx::PxVec3 center(0, -2.5f*arrowSize, 0); + physx::PxVec3 top(0, 0, 0 ); + + physx::PxVec3 _center = matrix.transform(center); + physx::PxVec3 _top = matrix.transform(top); + + + uint32_t saveState = mCurrentState.mStates; + + mCurrentState.setRenderState(RENDER_DEBUG::DebugRenderState::SolidWireShaded); + mCurrentState.mArrowColor = 0xFFFFFFFF; + + for (uint32_t i=0; i<pcount; i++) + { + physx::PxVec3 _p = matrix.transform( *p ); + physx::PxVec3 _prev = matrix.transform( *prev ); + + debugTri(&_p,&_center,&_prev); + debugTri(&_prev,&_top,&_p); + + prev = p; + p++; + } + mCurrentState.mStates = saveState; + + } + + PX_INLINE void debugCylinder(const DebugCylinder &d) + { + const uint32_t numOfSegments = uint32_t(4 << physx::PxMin(d.mSubdivision, 6u)); // this maxes out at 4^6 = 256 segments + const float segmentAngle = physx::PxTwoPi / numOfSegments; + const float c = physx::PxCos(segmentAngle); + const float s = physx::PxSin(segmentAngle); + const physx::PxMat33 rotY(physx::PxVec3(c, 0,-s), physx::PxVec3(0, 1.0f, 0), physx::PxVec3(s, 0, c)); + + const float radiusDiff = d.mRadius1 - d.mRadius2; + physx::PxVec3 heightVec(radiusDiff / 2.0f, d.mHeight / 2.0f, 0.0f); + + const float avgRadius = (d.mRadius1 + d.mRadius2) / 2.0f; + physx::PxVec3 currentVec(avgRadius, 0.0f, 0.0f); + physx::PxVec3 currentTangent(0.0f, 0.0f, 1.0f); + physx::PxVec3 currentNormal = heightVec.cross(currentTangent).getNormalized(); + + const physx::PxVec3 upperCenter(0.0f, d.mHeight / 2.0f, 0.0f); + const physx::PxVec3 lowerCenter(-upperCenter); + + + if (mCurrentState.isSolid()) + { + for( uint32_t i=0; i<numOfSegments; ++i ) + { + const physx::PxVec3 e0 = currentVec + heightVec; + const physx::PxVec3 e2 = currentVec - heightVec; + const physx::PxVec3 nC = currentNormal; + + currentVec = rotY.transform(currentVec); + heightVec = rotY.transform(heightVec); + currentTangent = rotY.transform(currentTangent); + const physx::PxVec3 e1 = currentVec + heightVec; + const physx::PxVec3 e3 = currentVec - heightVec; + const physx::PxVec3 nN = currentNormal = heightVec.cross(currentTangent).getNormalized(); + + debugTri(&e0, &e2, &e3, &nC, &nC, &nN); + debugTri(&e3, &e1, &e0, &nN, &nN, &nC); + + if (d.mCloseSides) + { + debugTri(&e0, &e1, &upperCenter); + debugTri(&e2, &lowerCenter, &e3); + } + else + { + debugTri(&e3, &e2, &e0, &nN, &nC, &nC); + debugTri(&e0, &e1, &e3, &nC, &nN, &nN); + } + } + } + else + { + for( uint32_t i=0; i<numOfSegments; ++i ) + { + const physx::PxVec3 e0 = currentVec + heightVec; + const physx::PxVec3 e2 = currentVec - heightVec; + + const physx::PxVec3 nextVec = rotY.transform(currentVec); + heightVec = rotY.transform(heightVec); + const physx::PxVec3 e1 = nextVec + heightVec; + const physx::PxVec3 e3 = nextVec - heightVec; + + //const physx::PxVec3 nC = (-currentVec).getNormalized(); + + debugLine(e0, e2); + debugLine(e0, e1); + debugLine(e2, e3); + + if (d.mCloseSides) + { + debugLine(upperCenter, e0); + debugLine(lowerCenter, e2); + } + currentVec = nextVec; + } + } + } + + PX_INLINE void debugCircle(const DebugCircle &d) + { + const uint32_t numOfSegments = uint32_t(4 << physx::PxMin(d.mSubdivision, 6u)); // this maxes out at 4^6 = 256 segments + const float segmentAngle = physx::PxTwoPi / numOfSegments; + const float c = physx::PxCos(segmentAngle); + const float s = physx::PxSin(segmentAngle); + + // rotation in ZX plane + const physx::PxMat33 rotY(physx::PxVec3(c, 0,-s), physx::PxVec3(0, 1.0f, 0), physx::PxVec3(s, 0, c)); + physx::PxVec3 currentVec(d.mRadius, 0.0f, 0.0f); + if (d.mDrawSolidCircle) + { + physx::PxVec3* points = new physx::PxVec3[numOfSegments]; + for( uint32_t i=0; i<numOfSegments; ++i, currentVec = rotY.transform(currentVec)) + { + points[i] = d.mTransform.transform(currentVec); + } + debugPolygon(numOfSegments, points); + delete[] points; + } + else + { + for( uint32_t i=0; i<numOfSegments; ++i ) + { + physx::PxVec3 p0 = currentVec; + physx::PxVec3 p1 = rotY.transform(currentVec); + currentVec = p1; + + p0 = d.mTransform.transform(p0); + p1 = d.mTransform.transform(p1); + debugLine(p0, p1); + } + } + } + + PX_INLINE void debugPolygon(uint32_t pcount,const physx::PxVec3 *points) + { + if ( mCurrentState.isSolid() ) + { + PX_ASSERT( pcount >= 3 ); + PX_ASSERT( pcount <= 256 ); + bool wasOverlay = mCurrentState.hasRenderState(RENDER_DEBUG::DebugRenderState::SolidWireShaded); + if( wasOverlay ) + { + mCurrentState.clearRenderState(RENDER_DEBUG::DebugRenderState::SolidWireShaded); + mCurrentState.incrementChangeCount(); + } + const physx::PxVec3 *v1 = &points[0]; + const physx::PxVec3 *v2 = &points[1]; + const physx::PxVec3 *v3 = &points[2]; + debugTri(v1, v2, v3, NULL, NULL, NULL, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, false); + for (uint32_t i=3; i<pcount; i++) + { + v2 = v3; + v3 = &points[i]; + debugTri(v1, v2, v3, NULL, NULL, NULL, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, false); + } + if ( wasOverlay ) + { + for (uint32_t i=0; i<(pcount-1); i++) + { + debugLine( points[i], points[i+1], mCurrentState.mArrowColor, mCurrentState.mArrowColor ); + } + debugLine(points[pcount-1],points[0]); + mCurrentState.setRenderState(RENDER_DEBUG::DebugRenderState::SolidWireShaded); + mCurrentState.incrementChangeCount(); + } + } + else + { + for (uint32_t i=0; i<(pcount-1); i++) + { + debugLine( points[i], points[i+1] ); + } + debugLine(points[pcount-1],points[0]); + } + } + + PX_INLINE void debugPointCylinder(const DebugPointCylinder &d) + { + physx::PxVec3 dir = d.mP2 - d.mP1; + dir.normalize(); + + physx::PxVec3 ref(0, 1.0f, 0); + + physx::PxQuat quat; + + rotationArc(ref,dir,quat); + + physx::PxMat44 matrix1(quat); + physx::PxMat44 matrix2(quat); + + matrix1.setPosition(d.mP2); + matrix2.setPosition(d.mP1); + + + uint32_t pcount = 0; + physx::PxVec3 points1[24]; + physx::PxVec3 points2[24]; + + physx::PxVec3 *dest1 = points1; + physx::PxVec3 *dest2 = points2; + + + for (float a=30; a<=360; a+=30) + { + float r = a*FM_DEG_TO_RAD; + float x = physx::PxCos(r)*d.mRadius; + float y = physx::PxSin(r)*d.mRadius; + + physx::PxVec3 p(x, 0, y); + + (*dest1) = matrix1.transform(p); + (*dest2) = matrix2.transform(p); + + dest1++; + dest2++; + pcount++; + + } + + PX_ASSERT( pcount < 24 ); + + if ( mCurrentState.isSolid() ) + { + + uint32_t saveState = mCurrentState.mStates; + mCurrentState.clearRenderState(RENDER_DEBUG::DebugRenderState::SolidWireShaded); + mCurrentState.setRenderState(RENDER_DEBUG::DebugRenderState::SolidShaded); + mCurrentState.clearRenderState(RENDER_DEBUG::DebugRenderState::CounterClockwise); + + physx::PxVec3 *prev1 = &points1[(pcount-1)]; + physx::PxVec3 *prev2 = &points2[(pcount-1)]; + + physx::PxVec3 *scan1 = points1; + physx::PxVec3 *scan2 = points2; + + for (uint32_t i=0; i<pcount; i++) + { + + debugTri(scan1,prev2,prev1); + debugTri(scan2,prev2,scan1); + + prev1 = scan1; + prev2 = scan2; + scan1++; + scan2++; + } + + debugPolygon(pcount,points2); + mCurrentState.setRenderState(RENDER_DEBUG::DebugRenderState::CounterClockwise); + debugPolygon(pcount,points1); + + mCurrentState.mStates = saveState; + + } + + if ( !mCurrentState.hasRenderState(RENDER_DEBUG::DebugRenderState::SolidShaded) || mCurrentState.hasRenderState(RENDER_DEBUG::DebugRenderState::SolidWireShaded) ) + { + + uint32_t color = mCurrentState.hasRenderState(RENDER_DEBUG::DebugRenderState::SolidWireShaded) ? mCurrentState.mArrowColor : mCurrentState.mColor; + physx::PxVec3 *prev1 = &points1[(pcount-1)]; + physx::PxVec3 *prev2 = &points2[(pcount-1)]; + + physx::PxVec3 *scan1 = points1; + physx::PxVec3 *scan2 = points2; + for (uint32_t i=0; i<pcount; i++) + { + debugLine(*scan1,*scan2,color,color); + + debugLine(d.mP2,*scan1,color,color); + debugLine(d.mP1,*scan2,color,color); + + debugLine(*prev1,*scan1,color,color); + debugLine(*prev2,*scan2,color,color); + + prev1 = scan1; + prev2 = scan2; + + scan1++; + scan2++; + } + } + } + + PX_INLINE void debugThickRay(const DebugThickRay &d) + { + RenderState save = mCurrentState; + + mCurrentState.clearRenderState(RENDER_DEBUG::DebugRenderState::SolidWireShaded); + mCurrentState.setRenderState(RENDER_DEBUG::DebugRenderState::SolidShaded); + + physx::PxVec3 dir = d.mP2 - d.mP1; + float mag = dir.normalize(); + float arrowSize = physx::PxMin(physx::PxMax(mCurrentState.mArrowSize, d.mRaySize * 1.3f), mag * 0.2f); + + physx::PxVec3 ref(0,1.0f,0); + physx::PxQuat quat; + + rotationArc(ref,dir,quat); + + physx::PxMat44 matrix(quat); + matrix.setPosition(d.mP2); + + + uint32_t pcount = 0; + physx::PxVec3 points[24]; + physx::PxVec3 *dest = points; + + for (float a=30; a<=360; a+=30) + { + float r = a*FM_DEG_TO_RAD; + float x = physx::PxCos(r)*arrowSize; + float y = physx::PxSin(r)*arrowSize; + + dest->x = x; + dest->y = -3*arrowSize; + dest->z = y; + + dest++; + pcount++; + } + + physx::PxVec3 *prev = &points[(pcount-1)]; + physx::PxVec3 *p = points; + physx::PxVec3 center(0, -2.5f*arrowSize, 0); + physx::PxVec3 top(0,0,0); + + physx::PxVec3 _center; + physx::PxVec3 _top; + + _center = matrix.transform(center); + _top = matrix.transform(top); + + DebugPointCylinder dc(d.mP1,_center,d.mRaySize); + debugPointCylinder(dc); + + //mCurrentState = save; - don't want triangles to be seen ! + mCurrentState.setRenderState(RENDER_DEBUG::DebugRenderState::SolidShaded); + mCurrentState.mColor = mCurrentState.mArrowColor; + mCurrentState.mArrowColor = mCurrentState.mOutlineColor; + + if(d.mArrowTip) + { + for (uint32_t i=0; i<pcount; i++) + { + + physx::PxVec3 _p; + physx::PxVec3 _prev; + + _p = matrix.transform(*p); + _prev = matrix.transform(*prev); + + debugTri(&_p,&_center,&_prev); + debugTri(&_prev,&_top,&_p); + + prev = p; + p++; + } + } + else + { + DebugDetailedSphere sphere(_center, 0.1f * mag, 2); + debugDetailedSphere(sphere); + } + + mCurrentState = save; + } + + void debugPlane(const physx::PxVec3 &normal,float dCoff,float radius1,float radius2) + { + physx::PxVec3 ref(0,1.0f,0); + physx::PxQuat quat; + rotationArc(ref,normal,quat); + physx::PxMat44 matrix(quat); + + float stepsize = 360/20; + + physx::PxVec3 prev(0,0,0); + + physx::PxVec3 origin(0,-dCoff,0); + physx::PxVec3 pos(origin), first(origin), center(origin); + + center = matrix.transform(origin); + matrix.setPosition(center); + + for (float d=0; d<360; d+=stepsize) + { + float a = degToRad(d); + physx::PxVec3 _pos(physx::PxCos(a)*radius1,0,physx::PxSin(a)*radius2); + pos = matrix.transform(_pos); + + debugLine(center,pos); + + if ( d == 0 ) + { + first = pos; + } + else + { + debugLine(prev,pos); + } + prev = pos; + } + + debugLine(first,pos); + } + + + + PX_INLINE void debugPlane(const DebugPlane &d) + { + debugPlane(d.mNormal,d.mD,d.mRadius1*0.25f, d.mRadius2*0.25f); + debugPlane(d.mNormal,d.mD,d.mRadius1*0.5f, d.mRadius2*0.5f); + debugPlane(d.mNormal,d.mD,d.mRadius1*0.75f, d.mRadius2*0.75f); + debugPlane(d.mNormal,d.mD,d.mRadius1*1.0f, d.mRadius2*1.0f); + } + + PX_INLINE void debugTriNormals(const DebugTriNormals &d) + { + debugTri(&d.mP1,&d.mP2,&d.mP3,&d.mN1,&d.mN2,&d.mN3); + } + + PX_INLINE void debugGradientTriNormals(const DebugGradientTriNormals &d) + { + debugTri(&d.mP1,&d.mP2,&d.mP3,&d.mN1,&d.mN2,&d.mN3,d.mC1,d.mC2,d.mC3,true); + } + + PX_INLINE void debugSphere(const DebugSquashedSphere &d) + { + for (uint32_t i = 0; i < 8; i++) + { + const physx::PxVec3 p0 = simpleSpherePosition[simpleSphereIndices[i*3+0]]; + const physx::PxVec3 p1 = simpleSpherePosition[simpleSphereIndices[i*3+1]]; + const physx::PxVec3 p2 = simpleSpherePosition[simpleSphereIndices[i*3+2]]; + subdivideOnSphere(int(d.mSubdivision), p0, p1, p2, d.mRadius, 0.0f, 0.0f); + } + } + + + PX_INLINE void debugSphere(const DebugSphere &d) + { + for (uint32_t i = 0; i < 8; i++) + { + const physx::PxVec3 p0 = simpleSpherePosition[simpleSphereIndices[i*3+0]]; + const physx::PxVec3 p1 = simpleSpherePosition[simpleSphereIndices[i*3+1]]; + const physx::PxVec3 p2 = simpleSpherePosition[simpleSphereIndices[i*3+2]]; + subdivideOnSphere(int(d.mSubdivision), p0, p1, p2, d.mRadius, 0.0f, 0.0f); + } + } + + void subdivideOnSphere(int subdivision, const physx::PxVec3& p0, const physx::PxVec3& p1, const physx::PxVec3& p2, float radius, float height, float skew) + { + //physx::PxMat44 transform = physx::PxMat44(physx::PxIdentity); + if (subdivision <= 0) + { + physx::PxVec3 t[3]; + physx::PxVec3 n[3] = { p0, p1, p2 }; + + if (height > 0.0f || skew != 0.0f) + { + const float upper = physx::PxSign(p0.y + p1.y + p2.y); + + const physx::PxVec3 offset(0.0f, upper * height, 0.0f); + if (skew != 0.0f) + { + const float scale = upper - skew; + for (uint32_t i = 0; i < 3; i++) + { + const float ny = n[i].y; + //const float sny =((ny - 1.0f) * scale) + upper; + const float sny = upper > 0.0f ? (1.0f - (1.0f - ny) * scale) : (-1.0f + (1.0f + ny) * -scale); + PX_ASSERT(physx::PxAbs(sny) <= 1.0f); + n[i].y = 0.0f; + n[i].normalize(); + n[i] *= physx::PxSqrt(1.0f - (sny * sny)); + n[i].y = sny; + t[i] = n[i] * radius + offset; + } + } + else + { + t[0] = p0 * radius + offset; + t[1] = p1 * radius + offset; + t[2] = p2 * radius + offset; + } + } + else + { + t[0] = p0 * radius; + t[1] = p1 * radius; + t[2] = p2 * radius; + } + + debugTri(t+0, t+1, t+2, n+0, n+1, n+2); + } + else + { + physx::PxVec3 p01 = p0 + p1; p01.normalize(); + physx::PxVec3 p12 = p1 + p2; p12.normalize(); + physx::PxVec3 p20 = p2 + p0; p20.normalize(); + + subdivideOnSphere(subdivision-1, p0, p01, p20, radius, height, skew); + subdivideOnSphere(subdivision-1, p1, p12, p01, radius, height, skew); + subdivideOnSphere(subdivision-1, p2, p20, p12, radius, height, skew); + subdivideOnSphere(subdivision-1, p01, p12, p20, radius, height, skew); + } + } + + + void subdivideOnSphere(int subdivision, const physx::PxVec3& p0, const physx::PxVec3& p1, const physx::PxVec3& p2, const physx::PxVec3 &radius, float height, float skew) + { + //physx::PxMat44 transform = physx::PxMat44(physx::PxIdentity); + if (subdivision <= 0) + { + physx::PxVec3 t[3]; + physx::PxVec3 n[3] = { p0, p1, p2 }; + + if (height > 0.0f || skew != 0.0f) + { + const float upper = physx::PxSign(p0.y + p1.y + p2.y); + + const physx::PxVec3 offset(0.0f, upper * height, 0.0f); + if (skew != 0.0f) + { + const float scale = upper - skew; + for (uint32_t i = 0; i < 3; i++) + { + const float ny = n[i].y; + //const float sny =((ny - 1.0f) * scale) + upper; + const float sny = upper > 0.0f ? (1.0f - (1.0f - ny) * scale) : (-1.0f + (1.0f + ny) * -scale); + PX_ASSERT(physx::PxAbs(sny) <= 1.0f); + n[i].y = 0.0f; + n[i].normalize(); + n[i] *= physx::PxSqrt(1.0f - (sny * sny)); + n[i].y = sny; + t[i] = n[i].multiply(radius) + offset; + } + } + else + { + t[0] = p0.multiply(radius) + offset; + t[1] = p1.multiply(radius) + offset; + t[2] = p2.multiply(radius) + offset; + } + } + else + { + t[0] = p0.multiply(radius); + t[1] = p1.multiply(radius); + t[2] = p2.multiply(radius); + } + + debugTri(t+0, t+1, t+2, n+0, n+1, n+2); + } + else + { + physx::PxVec3 p01 = p0 + p1; p01.normalize(); + physx::PxVec3 p12 = p1 + p2; p12.normalize(); + physx::PxVec3 p20 = p2 + p0; p20.normalize(); + + subdivideOnSphere(subdivision-1, p0, p01, p20, radius, height, skew); + subdivideOnSphere(subdivision-1, p1, p12, p01, radius, height, skew); + subdivideOnSphere(subdivision-1, p2, p20, p12, radius, height, skew); + subdivideOnSphere(subdivision-1, p01, p12, p20, radius, height, skew); + } + } + + + + PX_INLINE void debugCapsule(const DebugCapsule &d) + { + DebugCylinder c(d.mRadius,d.mHeight,d.mSubdivision,false); + debugCylinder(c); + + const float height = d.mHeight * 0.5f; + for (uint32_t i = 0; i < 8; i++) + { + const physx::PxVec3 p0 = simpleSpherePosition[simpleSphereIndices[i*3+0]]; + const physx::PxVec3 p1 = simpleSpherePosition[simpleSphereIndices[i*3+1]]; + const physx::PxVec3 p2 = simpleSpherePosition[simpleSphereIndices[i*3+2]]; + subdivideOnSphere(int(d.mSubdivision), p0, p1, p2, d.mRadius, height, 0.0f); + } + } + + void debugCone(const DebugCone &d) + { + physx::PxVec3 prev; + physx::PxVec3 orig(0,0,0); // = xform.getPosition(); + + physx::PxVec3 center(0,d.mLength,0); + + float s1 = tanf(d.mInnerAngle)*d.mLength; + float s2 = tanf(d.mOuterAngle)*d.mLength; + + float stepSize = 360.0f / static_cast<float>(d.mSubdivision); + + for (uint32_t i=0; i<=d.mSubdivision; i++) + { + float fv = static_cast<float>(i)*stepSize; + if ( i == d.mSubdivision ) + { + fv = 0; + } + float r = fv*FM_DEG_TO_RAD; + + float dx = s2*cosf(r); + float dy = s1*sinf(r); + + physx::PxVec3 v(dx,d.mLength,dy); + if ( i != 0 ) + { + debugTri(&orig,&prev,&v); + if ( d.mCloseEnd ) + { + debugTri(¢er,&v,&prev); + } + else + { + debugTri(&orig,&v,&prev); + } + } + prev = v; + } + + } + + void debugTaperedCapsule(const DebugTaperedCapsule& d) + { + physx::PxMat44* oldPose = mCurrentState.mPose; + physx::PxMat44 newPose = physx::PxMat44(physx::PxIdentity); + + uint32_t subdivision = d.mSubdivision; + + float radDiff = d.mRadius2 - d.mRadius1; + const float sinAlpha = radDiff / physx::PxSqrt(radDiff * radDiff + d.mHeight * d.mHeight); + + float sphereSeparation = 0; + float skew = 0; + float radius[] = { d.mRadius1, d.mRadius2 }; + + const uint32_t oldColor = mCurrentState.mColor; + + if (physx::PxAbs(sinAlpha) < 1.0f) + { + const float cosAlpha = physx::PxSqrt(1.0f - sinAlpha * sinAlpha); + + const uint32_t minSubdivision = uint32_t(sinAlpha * sinAlpha * 4.0f) + 1; + const uint32_t maxSubdivision = 6; + subdivision = physx::PxMin(physx::PxMax(minSubdivision, d.mSubdivision), maxSubdivision); + + const float heightOffset = sinAlpha * (d.mRadius1 + d.mRadius2) / 2.0f; + newPose.setPosition(newPose.getPosition() + physx::PxVec3(0.0f, heightOffset, 0.0f)); + if (oldPose != NULL) + { + newPose = *oldPose * newPose; + } + + // move the cylinder + mCurrentState.mPose = &newPose; + + // shrink the cylinder + const float height = d.mHeight - physx::PxAbs(sinAlpha * (d.mRadius1 - d.mRadius2)); + + DebugCylinder c(d.mRadius1 * cosAlpha, d.mRadius2 * cosAlpha, height, subdivision, false); + debugCylinder(c); + + // reset current pose + mCurrentState.mPose = oldPose; + + sphereSeparation = d.mHeight * 0.5f; + skew = sinAlpha; + } + else + { + mCurrentState.mColor = 0x7f7fff; // light blue + radius[0] = radius[1] = physx::PxMax(d.mRadius1, d.mRadius2); + } + + + for (uint32_t i = 0; i < 8; i++) + { + physx::PxVec3 p[] = + { + simpleSpherePosition[simpleSphereIndices[i*3+0]], + simpleSpherePosition[simpleSphereIndices[i*3+1]], + simpleSpherePosition[simpleSphereIndices[i*3+2]] + }; + + subdivideOnSphere(int(subdivision), p[0], p[1], p[2], radius[i >> 2], sphereSeparation, skew); + } + + mCurrentState.mColor = oldColor; + } + + void quickSphere(const physx::PxVec3 &p,float radius,uint32_t color) + { + mCurrentState.mColor = color; + mCurrentState.mArrowColor = color; + mCurrentState.mStates = (mCurrentState.mStates & ~RENDER_DEBUG::DebugRenderState::SolidWireShaded) | RENDER_DEBUG::DebugRenderState::SolidShaded; + DebugDetailedSphere ds(p,radius,2); + debugDetailedSphere(ds); + mCurrentState.mStates = (mCurrentState.mStates & ~RENDER_DEBUG::DebugRenderState::SolidShaded) | RENDER_DEBUG::DebugRenderState::SolidWireShaded; + } + + PX_INLINE void debugAxes(const DebugAxes &d) + { + physx::PxMat44 pose = d.mTransform; + float brightness = 1.0f - d.mBrightness; + + uint32_t red = getColor(255, 0, 0, brightness); + uint32_t green = getColor( 0,255, 0, brightness); + uint32_t blue = getColor( 0, 0,255, brightness); + uint32_t yellow = getColor(255,255, 0, brightness); + uint32_t white = getColor(255, 255, 255, brightness); + + uint32_t colorX = red, colorY = green, colorZ = blue; + if (d.mAxisSwitch & 4) //x + { + colorX = yellow; + } + if (d.mAxisSwitch & 2) //y + { + colorY = yellow; + } + if (d.mAxisSwitch & 1) //z + { + colorZ = yellow; + } + + physx::PxVec3 px(d.mDistance,0,0); + physx::PxVec3 py(0,d.mDistance,0); + physx::PxVec3 pz(0,0,d.mDistance); + + px = d.mTransform.transform(px); + py = d.mTransform.transform(py); + pz = d.mTransform.transform(pz); + + physx::PxVec3 t = d.mTransform.getPosition(); + + RenderState save = mCurrentState; + + mCurrentState.mArrowSize = d.mDistance*0.1f; + switch (d.mRenderMode) + { + case DebugAxesRenderMode::DEBUG_AXES_RENDER_SOLID: + { + quickSphere(t,d.mDistance*0.1f,yellow); + } + break; + case DebugAxesRenderMode::DEBUG_AXES_RENDER_LINES: + { + ; + } + break; + } + mCurrentState.mStates|=RENDER_DEBUG::DebugRenderState::CameraFacing; + mCurrentState.mStates|=RENDER_DEBUG::DebugRenderState::CenterText; + mCurrentState.mOutlineColor = white; + + float axisSwitchScaleStart = 1.0f; + float axisSwitchScaleEnd = 1.0f; + switch (d.mRenderMode) + { + case DebugAxesRenderMode::DEBUG_AXES_RENDER_SOLID: + { + axisSwitchScaleStart = 1.0f; + axisSwitchScaleEnd = 4.0f; + } + break; + case DebugAxesRenderMode::DEBUG_AXES_RENDER_LINES: + { + axisSwitchScaleStart = 0.0f; + axisSwitchScaleEnd = 1.0f; + } + break; + } + + if (d.mRenderMode == DebugAxesRenderMode::DEBUG_AXES_RENDER_LINES) + { + float triSizeFactor = 0.2f; + float circleSizeFactor = 0.1f; + + physx::PxMat44 inverseViewMatrix = mViewMatrix.inverseRT(); + mCurrentState.setRenderState(RENDER_DEBUG::DebugRenderState::DoubleSided); + mCurrentState.setRenderState(RENDER_DEBUG::DebugRenderState::SolidShaded); + + DebugCircle circleCfg(0.0f, 10, true); + circleCfg.mTransform.column0 = inverseViewMatrix.column1; + circleCfg.mTransform.column1 = inverseViewMatrix.column2; + circleCfg.mTransform.column2 = inverseViewMatrix.column0; + + physx::PxVec3 triNormal = physx::PxVec3(0,0,1); + { + mCurrentState.mColor = colorX; + mCurrentState.mArrowColor = colorX; + if (!d.mShowRotation) + { + physx::PxVec3 usedOrthoAxe = inverseViewMatrix.column2.getXYZ().cross(t - px); + usedOrthoAxe.normalize(); + usedOrthoAxe *= d.mDistance; + physx::PxVec3 arrowVertices[] = { + px + (t - px) * triSizeFactor + usedOrthoAxe * triSizeFactor, + px, + px + (t - px) * triSizeFactor - usedOrthoAxe * triSizeFactor, + }; + debugTri(arrowVertices+0, arrowVertices+1, arrowVertices+2, &triNormal, &triNormal, &triNormal, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, false); + debugLine(t, px + (t - px) * triSizeFactor); + } + else if (d.mShowRotation) + { + circleCfg.mRadius = ((t - px) * circleSizeFactor).magnitude(); + circleCfg.mTransform.setPosition(px + (t - px) * circleSizeFactor); + debugCircle(circleCfg); + debugLine(t, px + (t - px) * circleSizeFactor); + } + if ( d.mShowXYZ ) + { + mCurrentState.mTextScale = d.mDistance; + mCurrentState.mColor = white; + DebugText dt(px,physx::PxMat44(physx::PxIdentity),"X"); + debugText(dt); + } + } + + { + mCurrentState.mColor = colorY; + mCurrentState.mArrowColor = colorY; + if (!d.mShowRotation) + { + physx::PxVec3 usedOrthoAxe = inverseViewMatrix.column2.getXYZ().cross(t - py); + usedOrthoAxe.normalize(); + usedOrthoAxe *= d.mDistance; + physx::PxVec3 arrowVertices[] = { + py + (t - py) * triSizeFactor + usedOrthoAxe * triSizeFactor, + py, + py + (t - py) * triSizeFactor - usedOrthoAxe * triSizeFactor, + }; + debugTri(arrowVertices+0, arrowVertices+1, arrowVertices+2, &triNormal, &triNormal, &triNormal, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, false); + debugLine(t, py + (t - py) * triSizeFactor); + } + else if (d.mShowRotation) + { + circleCfg.mRadius = ((t - py) * circleSizeFactor).magnitude(); + circleCfg.mTransform.setPosition(py + (t - py) * circleSizeFactor); + debugCircle(circleCfg); + debugLine(t, py + (t - py) * circleSizeFactor); + } + if ( d.mShowXYZ ) + { + mCurrentState.mTextScale = d.mDistance; + mCurrentState.mColor = white; + DebugText dt(py,physx::PxMat44(physx::PxIdentity),"Y"); + debugText(dt); + } + } + + { + mCurrentState.mColor = colorZ; + mCurrentState.mArrowColor = colorZ; + if (!d.mShowRotation) + { + physx::PxVec3 usedOrthoAxe = inverseViewMatrix.column2.getXYZ().cross(t - pz); + usedOrthoAxe.normalize(); + usedOrthoAxe *= d.mDistance; + + physx::PxVec3 arrowVertices[] = { + pz + (t - pz) * triSizeFactor + usedOrthoAxe * triSizeFactor, + pz, + pz + (t - pz) * triSizeFactor - usedOrthoAxe * triSizeFactor, + }; + debugTri(arrowVertices+0, arrowVertices+1, arrowVertices+2, &triNormal, &triNormal, &triNormal, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, false); + debugLine(t, pz + (t - pz) * triSizeFactor); + } + else if (d.mShowRotation) + { + circleCfg.mRadius = ((t - pz) * circleSizeFactor).magnitude(); + circleCfg.mTransform.setPosition(pz + (t - pz) * circleSizeFactor); + debugCircle(circleCfg); + debugLine(t, pz + (t - pz) * circleSizeFactor); + } + if ( d.mShowXYZ ) + { + mCurrentState.mTextScale = d.mDistance; + mCurrentState.mColor = white; + DebugText dt(pz,physx::PxMat44(physx::PxIdentity),"Z"); + debugText(dt); + } + } + } + else if (d.mRenderMode == DebugAxesRenderMode::DEBUG_AXES_RENDER_SOLID) + { + { + mCurrentState.mColor = colorX; + mCurrentState.mArrowColor = colorX; + + DebugThickRay dr(t, px, d.mDistance * 0.02f, !d.mShowRotation); + debugThickRay(dr); + + if ( d.mShowXYZ ) + { + mCurrentState.mTextScale = d.mDistance; + mCurrentState.mColor = white; + DebugText dt(px,physx::PxMat44(physx::PxIdentity),"X"); + debugText(dt); + } + } + + { + mCurrentState.mColor = colorY; + mCurrentState.mArrowColor = colorY; + DebugThickRay dr(t, py, d.mDistance*0.02f, !d.mShowRotation); + debugThickRay(dr); + if ( d.mShowXYZ ) + { + mCurrentState.mTextScale = d.mDistance; + mCurrentState.mColor = white; + DebugText dt(py,physx::PxMat44(physx::PxIdentity),"Y"); + debugText(dt); + } + } + { + mCurrentState.mColor = colorZ; + mCurrentState.mArrowColor = colorZ; + DebugThickRay dr(t, pz, d.mDistance * 0.02f, !d.mShowRotation); + debugThickRay(dr); + if ( d.mShowXYZ ) + { + mCurrentState.mTextScale = d.mDistance; + mCurrentState.mColor = white; + DebugText dt(pz,physx::PxMat44(physx::PxIdentity),"Z"); + debugText(dt); + } + } + } + + if ( d.mAxisSwitch ) + { + physx::PxVec3 p1, p2; + uint32_t brightYellow = getColor(255, 255, 0, 0.0f); + mCurrentState.mColor = brightYellow; + + if (d.mAxisSwitch & 4) //x + { + p1 = physx::PxVec3(-1.0f * axisSwitchScaleStart, 0.0f, 0.0f); + p2 = physx::PxVec3(1.0f * axisSwitchScaleEnd, 0.0f, 0.0f); + p1 = pose.transform(p1); + p2 = pose.transform(p2); + + debugLine(p1, p2); + } + if(d.mAxisSwitch & 2) //y + { + p1 = physx::PxVec3(0.0f, -1.0f * axisSwitchScaleStart, 0.0f); + p2 = physx::PxVec3(0.0f, 1.0f * axisSwitchScaleEnd, 0.0f); + p1 = pose.transform(p1); + p2 = pose.transform(p2); + + debugLine(p1, p2); + } + if(d.mAxisSwitch & 1) //z + { + p1 = physx::PxVec3(0.0f, 0.0f, -1.0f * axisSwitchScaleStart); + p2 = physx::PxVec3(0.0f, 0.0f, 1.0f * axisSwitchScaleEnd); + p1 = pose.transform(p1); + p2 = pose.transform(p2); + + debugLine(p1, p2); + } + } + + mCurrentState = save; + } + + PX_INLINE void debugArc(const DebugArc &d) + { + if ( d.mShowRoot ) + { + debugLine(d.mCenter,d.mP1,0xFFFFFFFF,0xFFFFFFFF); + debugLine(d.mCenter,d.mP2,0xFFFFFFFF,0xFFFFFFFF); + } + + physx::PxVec3 v1 = d.mP1-d.mCenter; + float d1 = v1.normalize(); + physx::PxVec3 v2 = d.mP2-d.mCenter; + float d2 = v2.normalize(); + + physx::PxQuat quat; + rotationArc(v1,v2,quat); + + physx::PxQuat q1 = physx::PxQuat(physx::PxIdentity); + physx::PxQuat q2 = quat; + + physx::PxVec3 prev(0.0f); + + int32_t count = 0; + for (float st=0; st<=(1.01f); st+=0.05f) + { + float dst = ((d2-d1)*st)+d1; + physx::PxQuat q; + q = slerp(st,q1,q2); + physx::PxMat44 m(q); + m.setPosition(d.mCenter); + physx::PxVec3 t = v1*dst; + t = m.transform(t); + if ( st != 0 ) + { + if ( count == 20 ) + { + DebugRay dr(prev,t); + debugRay(dr); + } + else + debugLine(prev,t); + } + prev = t; + count++; + } + + } + + PX_INLINE void debugThickArc(const DebugThickArc &d) + { + if ( d.mShowRoot ) + { + debugLine(d.mCenter,d.mP1,0xFFFFFFFF,0xFFFFFFFF); + debugLine(d.mCenter,d.mP2,0xFFFFFFFF,0xFFFFFFFF); + } + + physx::PxVec3 v1 = d.mP1-d.mCenter; + float d1 = v1.normalize(); + physx::PxVec3 v2 = d.mP2-d.mCenter; + float d2 = v2.normalize(); + + physx::PxQuat quat; + rotationArc(v1,v2,quat); + + physx::PxQuat q1 = physx::PxQuat(physx::PxIdentity); + physx::PxQuat q2 = quat; + + physx::PxVec3 prev(0.0f); + + int32_t count = 0; + + for (float st=0; st<=(1.01f); st+=0.05f) + { + float dst = ((d2-d1)*st)+d1; + physx::PxQuat q; + q = slerp(st,q1,q2); + physx::PxMat44 m(q); + m.setPosition(d.mCenter); + physx::PxVec3 t = v1*dst; + t = m.transform(t); + if ( st != 0 ) + { +#if 0 + if ( count == 20 ) + { + float asave = mCurrentState.mArrowSize; + mCurrentState.mArrowSize = d.mThickness*4; + DebugThickRay dr(prev,t,d.mThickness); + debugThickRay(dr); + mCurrentState.mArrowSize = asave; + } + else +#endif + { + uint32_t save = mCurrentState.mStates; + + mCurrentState.clearRenderState(RENDER_DEBUG::DebugRenderState::SolidWireShaded); + mCurrentState.setRenderState(RENDER_DEBUG::DebugRenderState::SolidShaded); + + DebugPointCylinder dc(prev,t,d.mThickness); + debugPointCylinder(dc); + + mCurrentState.mStates = save; + } + } + prev = t; + count++; + } + } + + void debugFrustumPlane(const physx::PxVec4 &_p1,const physx::PxVec4 &_p2,const physx::PxVec4 &_p3,const physx::PxVec4 &_p4,uint32_t color) + { + physx::PxVec3 p1(_p1.x,_p1.y,_p1.z); + physx::PxVec3 p2(_p2.x,_p2.y,_p2.z); + physx::PxVec3 p3(_p3.x,_p3.y,_p3.z); + physx::PxVec3 p4(_p4.x,_p4.y,_p4.z); + + uint32_t save = mCurrentState.mStates; + uint32_t saveColor = mCurrentState.mColor; + mCurrentState.mColor = color; + +// mCurrentState.clearRenderState(RENDER_DEBUG::DebugRenderState::SolidWireShaded); +// mCurrentState.setRenderState(RENDER_DEBUG::DebugRenderState::SolidShaded); + + DebugTri t1(p1,p2,p3); + DebugTri t2(p1,p3,p4); + + debugTri(&p1,&p2,&p3); + debugTri(&p1,&p3,&p4); + + debugTri(&p3,&p2,&p1); + debugTri(&p4,&p3,&p1); + + debugLine(p1,p2,0xFFFFFF,0xFFFFFF); + debugLine(p2,p3,0xFFFFFF,0xFFFFFF); + debugLine(p3,p4,0xFFFFFF,0xFFFFFF); + debugLine(p4,p1,0xFFFFFF,0xFFFFFF); + + mCurrentState.mStates = save; + mCurrentState.mColor = saveColor; + + } + + PX_INLINE void debugFrustum(const physx::PxMat44 &iview,const physx::PxMat44 &proj) + { + // actually debug it here! + physx::PxMat44 viewProj = proj*iview; + physx::PxMat44 iviewProj = invert(viewProj); + + physx::PxMat44 view = invert(iview); + DebugAxes d(view,0.3f,1.0f,false,false,4, DebugAxesRenderMode::DEBUG_AXES_RENDER_SOLID); + debugAxes(d); // debug visualize the view matrix + + physx::PxVec4 v[8]; + + + v[0] = physx::PxVec4(-1.0f,-1.0f,0,1.0f); + v[1] = physx::PxVec4(1.0f,-1.0f,0,1.0f); + v[2] = physx::PxVec4(1.0f,1.0f,0,1.0f); + v[3] = physx::PxVec4(-1.0f,1.0f,0,1.0f); + + v[4] = physx::PxVec4(-1.0f,-1.0f,0.99999f,1.0f); + v[5] = physx::PxVec4(1.0f,-1.0f,0.99999f,1.0f); + v[6] = physx::PxVec4(1.0f,1.0f,0.99999f,1.0f); + v[7] = physx::PxVec4(-1.0f,1.0f,0.99999f,1.0f); + + + + for (uint32_t i=0; i<8; i++) + { + v[i] = iviewProj.transform(v[i]); + v[i]*=1.0f/v[i].w; // unproject the point. + } + + debugFrustumPlane(v[0],v[1],v[2],v[3],0xFF0000); + debugFrustumPlane(v[4],v[5],v[6],v[7],0xFF0000); + + debugFrustumPlane(v[0],v[3],v[7],v[4],0x00FF00); + debugFrustumPlane(v[1],v[2],v[6],v[5],0x00FF00); + + debugFrustumPlane(v[1],v[0],v[4],v[5],0x0000FF); + debugFrustumPlane(v[2],v[3],v[7],v[6],0x0000FF); + + + } + + PX_INLINE void debugDetailedSphere(const DebugDetailedSphere &d) + { + physx::PxMat44* save = mCurrentState.mPose; + //physx::PxVec3 origTranslation = save != NULL ? save->getPosition() : physx::PxVec3(0.0f); + physx::PxMat44 myPose = physx::PxMat44(physx::PxIdentity); + myPose.setPosition(d.mPos); + if (save != NULL) + { + myPose = *save * myPose; + } + mCurrentState.mPose = &myPose; + + DebugSphere d2(d.mRadius, d.mStepCount); + debugSphere(d2); + + mCurrentState.mPose = save; + } + + void skipString(physx::PsMemoryBuffer &mb) + { + char c; + uint32_t r = mb.read(&c,1); + while ( r && c ) + { + r = mb.read(&c,1); + } + } + + void debugCreateTriangleMesh(const DebugCreateTriangleMesh &dgs,RENDER_DEBUG::RenderDebugInterface *iface) + { + const void *data = static_cast<const void *>(&dgs); + physx::PsMemoryBuffer mb(data,dgs.mSize); + mb.setEndianMode(physx::PxFileBuf::ENDIAN_NONE); + nvidia::StreamIO stream(mb,dgs.mSize); + uint32_t cmd,size; + stream >> cmd; + stream >> size; + PX_ASSERT(cmd==DebugCommand::DEBUG_CREATE_TRIANGLE_MESH); + PX_ASSERT(size==dgs.mSize); + uint32_t vcount=0; + uint32_t tcount=0; + uint32_t meshId=0; + stream >> meshId; + stream >> vcount; + stream >> tcount; + const uint8_t *scan = mb.getReadLoc(); + const RENDER_DEBUG::RenderDebugMeshVertex *vertices = reinterpret_cast<const RENDER_DEBUG::RenderDebugMeshVertex *>(scan); + const uint32_t *indices = NULL; + if ( tcount ) + { + scan+=(vcount*sizeof(RENDER_DEBUG::RenderDebugMeshVertex)); + indices = reinterpret_cast<const uint32_t *>(scan); + } + if ( iface ) + { + iface->createTriangleMesh(meshId,vcount,vertices,tcount,indices); + } + } + + void debugRefreshTriangleMeshVertices(const DebugRefreshTriangleMeshVertices &dgs,RENDER_DEBUG::RenderDebugInterface *iface) + { + const void *data = static_cast<const void *>(&dgs); + physx::PsMemoryBuffer mb(data,dgs.mSize); + mb.setEndianMode(physx::PxFileBuf::ENDIAN_NONE); + nvidia::StreamIO stream(mb,dgs.mSize); + uint32_t cmd,size; + stream >> cmd; + stream >> size; + PX_ASSERT(cmd==DebugCommand::DEBUG_REFRESH_TRIANGLE_MESH_VERTICES); + PX_ASSERT(size==dgs.mSize); + uint32_t vcount=0; + uint32_t meshId=0; + stream >> meshId; + stream >> vcount; + const uint8_t *scan = mb.getReadLoc(); + const RENDER_DEBUG::RenderDebugMeshVertex *vertices = reinterpret_cast<const RENDER_DEBUG::RenderDebugMeshVertex *>(scan); + const uint32_t *indices = NULL; + scan+=(vcount*sizeof(RENDER_DEBUG::RenderDebugMeshVertex)); + indices = reinterpret_cast<const uint32_t *>(scan); + if ( iface ) + { + iface->refreshTriangleMeshVertices(meshId,vcount,vertices,indices); + } + } + + + void debugRenderTriangleMeshInstances(const DebugRenderTriangleMeshInstances &dgs,RENDER_DEBUG::RenderDebugInterface *iface) + { + const void *data = static_cast<const void *>(&dgs); + physx::PsMemoryBuffer mb(data,dgs.mSize); + mb.setEndianMode(physx::PxFileBuf::ENDIAN_NONE); + nvidia::StreamIO stream(mb,dgs.mSize); + uint32_t cmd,size; + stream >> cmd; + stream >> size; + PX_ASSERT(cmd==DebugCommand::DEBUG_RENDER_TRIANGLE_MESH_INSTANCES); + PX_ASSERT(size==dgs.mSize); + uint32_t instanceCount=0; + uint32_t meshId=0; + stream >> meshId; + stream >> instanceCount; + if ( instanceCount && iface ) + { + const uint8_t *scan = mb.getReadLoc(); + const RENDER_DEBUG::RenderDebugInstance *instances = reinterpret_cast<const RENDER_DEBUG::RenderDebugInstance *>(scan); + iface->renderTriangleMeshInstances(meshId,mCurrentState.mTexture1,mCurrentState.mTileRate1,mCurrentState.mTexture2,mCurrentState.mTileRate2,instanceCount,instances); + } + } + + void debugConvexHull(const DebugConvexHull &dgs) + { + const void *data = static_cast<const void *>(&dgs); + physx::PsMemoryBuffer mb(data,dgs.mSize); + mb.setEndianMode(physx::PxFileBuf::ENDIAN_NONE); + nvidia::StreamIO stream(mb,dgs.mSize); + uint32_t cmd,size; + stream >> cmd; + stream >> size; + PX_ASSERT(cmd==DebugCommand::DEBUG_CONVEX_HULL); + PX_ASSERT(size==dgs.mSize); + uint32_t planeCount=0; + stream >> planeCount; + if ( planeCount ) + { + const uint8_t *scan = mb.getReadLoc(); + const float *planes = reinterpret_cast<const float *>(scan); + + Hull2MeshEdges *h = createHull2MeshEdges(); + if ( !mCurrentState.hasRenderState(RENDER_DEBUG::DebugRenderState::SolidShaded)) + { + uint32_t edgeCount; + const HullEdge *edges = h->getHullEdges(planeCount, reinterpret_cast<const physx::PxPlane *>(planes), edgeCount); + if ( edges ) + { + uint32_t saveColor = mCurrentState.mColor; + mCurrentState.mColor = mCurrentState.mArrowColor; + for (uint32_t i=0; i<edgeCount; i++) + { + const HullEdge &e = edges[i]; + debugLine(e.e0,e.e1); + } + mCurrentState.mColor = saveColor; + } + } + if ( mCurrentState.hasRenderState(RENDER_DEBUG::DebugRenderState::SolidShaded) || mCurrentState.hasRenderState(RENDER_DEBUG::DebugRenderState::SolidWireShaded) ) + { + HullMesh m; + if ( h->getHullMesh(planeCount, reinterpret_cast<const physx::PxPlane *>(planes), m) ) + { + uint32_t saveState = mCurrentState.mStates; + mCurrentState.mStates&=~RENDER_DEBUG::DebugRenderState::SolidWireShaded; + mCurrentState.mStates|=RENDER_DEBUG::DebugRenderState::SolidShaded; + for (uint32_t i=0; i<m.mTriCount; i++) + { + uint16_t i1 = m.mIndices[i*3+0]; + uint16_t i2 = m.mIndices[i*3+1]; + uint16_t i3 = m.mIndices[i*3+2]; + const physx::PxVec3 &p1 = m.mVertices[i1]; + const physx::PxVec3 &p2 = m.mVertices[i2]; + const physx::PxVec3 &p3 = m.mVertices[i3]; + debugTri(&p1,&p2,&p3); + } + mCurrentState.mStates = saveState; + } + } + h->release(); + } + + } + + void debugRenderPoints(const DebugRenderPoints &dgs,RENDER_DEBUG::RenderDebugInterface *iface) + { + const void *data = static_cast<const void *>(&dgs); + physx::PsMemoryBuffer mb(data,dgs.mSize); + mb.setEndianMode(physx::PxFileBuf::ENDIAN_NONE); + nvidia::StreamIO stream(mb,dgs.mSize); + uint32_t cmd,size; + stream >> cmd; + stream >> size; + PX_ASSERT(cmd==DebugCommand::DEBUG_RENDER_POINTS); + PX_ASSERT(size==dgs.mSize); + uint32_t pointCount=0; + uint32_t meshId=0; + uint32_t mode=0; + uint32_t textureId1; + float textureTile1; + uint32_t textureId2; + float textureTile2; + stream >> meshId; + stream >> mode; + stream >> textureId1; + stream >> textureTile1; + stream >> textureId2; + stream >> textureTile2; + stream >> pointCount; + if ( pointCount && iface ) + { + const uint8_t *scan = mb.getReadLoc(); + const float *points = reinterpret_cast<const float *>(scan); + iface->debugPoints(static_cast<RENDER_DEBUG::PointRenderMode>(mode),meshId,mCurrentState.mArrowColor,mCurrentState.mArrowSize,textureId1,textureTile1,textureId2,textureTile2,pointCount,points); + } + } + + void debugRenderTriangles(const DebugRenderTriangles &dgs,RENDER_DEBUG::RenderDebugInterface *iface) + { + const void *data = static_cast<const void *>(&dgs); + physx::PsMemoryBuffer mb(data,dgs.mSize); + mb.setEndianMode(physx::PxFileBuf::ENDIAN_NONE); + nvidia::StreamIO stream(mb,dgs.mSize); + uint32_t cmd,size; + stream >> cmd; + stream >> size; + PX_ASSERT(cmd==DebugCommand::DEBUG_RENDER_TRIANGLES); + PX_ASSERT(size==dgs.mSize); + uint32_t tcount; + uint32_t useZ; + uint32_t isScreenSpace; + stream >> tcount; + stream >> useZ; + stream >> isScreenSpace; + if ( tcount && iface ) + { + const uint8_t *scan = mb.getReadLoc(); + const RenderDebugSolidVertex *points = reinterpret_cast<const RenderDebugSolidVertex *>(scan); + iface->debugRenderTriangles(tcount,points,useZ ? true : false,isScreenSpace ? true : false); + } + } + + void debugRenderLines(const DebugRenderLines &dgs,RENDER_DEBUG::RenderDebugInterface *iface) + { + const void *data = static_cast<const void *>(&dgs); + physx::PsMemoryBuffer mb(data,dgs.mSize); + mb.setEndianMode(physx::PxFileBuf::ENDIAN_NONE); + nvidia::StreamIO stream(mb,dgs.mSize); + uint32_t cmd,size; + stream >> cmd; + stream >> size; + PX_ASSERT(cmd==DebugCommand::DEBUG_RENDER_LINES); + PX_ASSERT(size==dgs.mSize); + uint32_t lcount; + uint32_t useZ; + uint32_t isScreenSpace; + stream >> lcount; + stream >> useZ; + stream >> isScreenSpace; + if ( lcount && iface ) + { + const uint8_t *scan = mb.getReadLoc(); + const RenderDebugVertex *lines = reinterpret_cast<const RenderDebugVertex *>(scan); + iface->debugRenderLines(lcount,lines,useZ ? true : false, isScreenSpace ? true : false ); + } + } + + + + void debugGraph(const DebugGraphStream &dgs) + { + const void *data = static_cast<const void *>(&dgs); + physx::PsMemoryBuffer mb(data,dgs.mSize); + mb.setEndianMode(physx::PxFileBuf::ENDIAN_NONE); + nvidia::StreamIO stream(mb,dgs.mSize); + uint32_t cmd,size; + stream >> cmd; + stream >> size; + PX_ASSERT(cmd==DebugCommand::DEBUG_GRAPH); + PX_ASSERT(size==dgs.mSize); + + DebugGraphDesc d; + + stream >> d.mNumPoints; + d.mGraphXLabel = reinterpret_cast<const char *>(mb.getReadLoc()); + skipString(mb); + d.mGraphYLabel = reinterpret_cast<const char *>(mb.getReadLoc()); + skipString(mb); + + mb.alignRead(4); + + d.mPoints = reinterpret_cast<const float *>(mb.getReadLoc()); + mb.advanceReadLoc(sizeof(uint32_t)*d.mNumPoints); + stream >> d.mCutOffLevel; + stream >> d.mGraphMax; + stream >> d.mGraphXPos; + stream >> d.mGraphYPos; + stream >> d.mGraphWidth; + stream >> d.mGraphHeight; + stream >> d.mGraphColor; + stream >> d.mArrowColor; + stream >> d.mColorSwitchIndex; + debugGraph(d); + } + + void debugGraph(const DebugGraphDesc& graphDesc) + { + // todo where should colors go??? + const uint32_t black = getColor(0, 0, 0); + const uint32_t blue = getColor(0, 0, 255); + const uint32_t green = getColor(0, 255, 0); + + RenderState saveState = mCurrentState; + + mCurrentState.setRenderState(RENDER_DEBUG::DebugRenderState::ScreenSpace); + mCurrentState.setRenderState(RENDER_DEBUG::DebugRenderState::NoZbuffer); + mCurrentState.clearRenderState(RENDER_DEBUG::DebugRenderState::SolidShaded); + + mCurrentState.mTextScale = 0.1f; + float textHeight = 0.04f; //in screen space -- would be nice to know this! + + if(graphDesc.mCutOffLevel != 0.0f) + { + mCurrentState.setCurrentColor(blue, black); + debugLine( + physx::PxVec3(graphDesc.mGraphXPos, graphDesc.mGraphYPos + graphDesc.mCutOffLevel, 0.0f), + physx::PxVec3(graphDesc.mGraphXPos + graphDesc.mGraphWidth, graphDesc.mGraphYPos + graphDesc.mCutOffLevel, 0.0f)); + } + + mCurrentState.setCurrentColor(graphDesc.mGraphColor, graphDesc.mArrowColor); //set the draw colors + if( strlen(graphDesc.mGraphXLabel) > 0 ) + { + DebugText txt( physx::PxVec3(graphDesc.mGraphXPos, graphDesc.mGraphYPos - textHeight,0),physx::PxMat44(physx::PxIdentity),graphDesc.mGraphXLabel); + debugText(txt); + } + if( graphDesc.mGraphYLabel[0] ) + { + DebugText txt(physx::PxVec3(graphDesc.mGraphXPos, graphDesc.mGraphYPos + graphDesc.mGraphHeight, 0), physx::PxMat44(physx::PxIdentity), graphDesc.mGraphYLabel); + debugText(txt); + } + + float lastX = graphDesc.mGraphXPos; + float lastY = graphDesc.mGraphYPos; + for (uint32_t i = 0; i < graphDesc.mNumPoints; i++) + { + float pointY = graphDesc.mPoints[i]; + pointY = graphDesc.mGraphYPos + pointY * graphDesc.mGraphHeight / graphDesc.mGraphMax; //scale to screen + float x = graphDesc.mGraphXPos + graphDesc.mGraphWidth * i / graphDesc.mNumPoints; + + if (graphDesc.mColorSwitchIndex == i) + mCurrentState.setCurrentColor( graphDesc.mArrowColor, + graphDesc.mGraphColor); //swap the colors + + debugLine(physx::PxVec3(lastX,lastY,0), physx::PxVec3(x,pointY,0)); + lastY = pointY; + lastX = x; + } + + //graph axes + mCurrentState.setCurrentColor(green, green); + //screen space test line + debugLine( physx::PxVec3(graphDesc.mGraphXPos, graphDesc.mGraphYPos,0), + physx::PxVec3(graphDesc.mGraphXPos, graphDesc.mGraphYPos + graphDesc.mGraphHeight,0)); + debugLine( physx::PxVec3(graphDesc.mGraphXPos, graphDesc.mGraphYPos,0), + physx::PxVec3(graphDesc.mGraphXPos + graphDesc.mGraphWidth, graphDesc.mGraphYPos,0)); + + mCurrentState = saveState; + } + + + virtual void setViewMatrix(const physx::PxMat44 &view) + { + mViewMatrix = view; + } + + virtual void finalizeFrame(void) + { + + } + +private: + +uint32_t mLineVertexCount; +uint32_t mMaxLineVertexCount; +RENDER_DEBUG::RenderDebugVertex *mLines; + +uint32_t mSolidVertexCount; +uint32_t mMaxSolidVertexCount; +RENDER_DEBUG::RenderDebugSolidVertex *mTriangles; + +RENDER_DEBUG::RenderDebugInterface *mInterface; +DisplayType mDisplayType; +RenderState mCurrentState; +MyVectorFont mVectorFont; +physx::PxMat44 mViewMatrix; + +}; + +// + +ProcessRenderDebug * createProcessRenderDebug(void) +{ + ProcessRenderDebugImpl *m = PX_NEW(ProcessRenderDebugImpl); + return static_cast< ProcessRenderDebug *>(m); +} + + +} // end of namespace |