From 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 Mon Sep 17 00:00:00 2001 From: git perforce import user Date: Tue, 25 Oct 2016 12:29:14 -0600 Subject: Initial commit: PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167] --- KaplaDemo/samples/sampleViewer3/SampleViewer.cpp | 2527 ++++++++++++++++++++++ 1 file changed, 2527 insertions(+) create mode 100644 KaplaDemo/samples/sampleViewer3/SampleViewer.cpp (limited to 'KaplaDemo/samples/sampleViewer3/SampleViewer.cpp') diff --git a/KaplaDemo/samples/sampleViewer3/SampleViewer.cpp b/KaplaDemo/samples/sampleViewer3/SampleViewer.cpp new file mode 100644 index 00000000..96b395af --- /dev/null +++ b/KaplaDemo/samples/sampleViewer3/SampleViewer.cpp @@ -0,0 +1,2527 @@ +// =============================================================================== +// Title: Sample Viewer +// Description: A Viewer for GRB Demo Scenes +// +// Written by: Matthias Müller (23.11.11) +// =============================================================================== + +#ifndef _SCL_SECURE_NO_WARNINGS +#define _SCL_SECURE_NO_WARNINGS +#endif + +#ifdef WIN32 +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include +#endif + + +#undef random + +#include +#include + +#include "ShaderShadow.h" +#include "ShadowMap.h" +#include "RenderTarget.h" + +#include + +#include "SampleViewer.h" +#include "MediaPath.h" + +#include +#include "cudamanager/PxCudaContextManager.h" + +#include "PxPhysics.h" +#include "PxCooking.h" +#include "PxDefaultAllocator.h" +#include "PxDefaultErrorCallback.h" +#include "PxDefaultCpuDispatcher.h" +#include "PxExtensionsAPI.h" +#include "PxPhysicsVersion.h" + +#include "PxScene.h" +#include "PxGpu.h" + +#include "foundation/PxFoundationVersion.h" +#include "foundation/PxProfiler.h" +#include "pvd/PxPvd.h" + +//namespace PVD { +// using namespace physx::debugger; +// using namespace physx::debugger::comm; +//} +#include "Timing.h" +#include "GLFontRenderer.h" +#include "BmpFile.h" + +#include "SceneKaplaTower.h" +#include "SceneKaplaArena.h" +#include "SceneRagdollWashingMachine.h" +#include "SceneVehicle.h" +#include "SceneCrab.h" + +#include +#include +//#include "fomHelper.h" +#include +#include "MyShaders.h" +#include "SimScene.h" +#include "Texture.h" +#include "AABox.h" +#include "SSAOHelper.h" +#include "HBAOHelper.h" +#include "FXAAHelper.h" +#include "IJGWin32/CPPJPEGWrapper.h" +#include "HDRHelper.h" +#include "SampleViewerGamepad.h" + +#include "PhysXMacros.h" + +#include "pvd/PxPvdTransport.h" +#include "foundation/PxMat44.h" + +#define SCREEN_DUMP_PATH "C:\\Capture\\%05i.bmp" + +int DEFAULT_SOLVER_ITERATIONS = 8; + + +#define WINDOW_WIDTH 1280 +#define WINDOW_HEIGHT 720 + +#define ENABLE_PVD 1 +#define FULL_PVD 0 + +// Globals ------------------------------------------------------------------------------------------- + +int gPhysicsFrameNumber = 0; // different from gFrameNr since the latter is for graphics +// --------------------------------------------------------------------------------------------------- +float g_fogStart = 150.0f; +float g_fogEnd = 350.0f; +float shadowClipNear = 0.01f; +float shadowClipFar = 80.0f; + +int gNrWorkerThreads = 4; + + +extern float g_shadowAdd; +const float zNear = 0.1f; +const float zFar = 1000.0f; + +SSAOHelper* gSSAOHelper = NULL; +HBAOHelper* gHBAOHelper = NULL; +FXAAHelper* gFXAAHelper = NULL; +HDRHelper* gHDRHelper = NULL; +GLenum shadowMapType = GL_TEXTURE_2D_ARRAY_EXT; +// PhysX +PxPhysics* gPxPhysics = NULL; +PxFoundation* gPxFoundation = NULL; +PxCooking* gPxCooking = NULL; +PxDefaultAllocator gAllocator; + +PxScene* gPxScene = NULL; +PxDefaultCpuDispatcher* gPxDispatcher = NULL; + +PxCudaContextManager* gCudaContextManager; + +bool gUseGrb = true; +bool gCurrentUsingGrb = gUseGrb; + +bool gForceSceneRecreate = false; +int gCountdownToRecereate = 2; + +bool gShot = false; + +PxU32 gMaxSubSteps = 1u; + +// Physics param +PxVec3 gDefaultGravity(0.0f ,-10.0f, 0.0f); +float gTimeStepSize = 1.0f / 60.0f; +float gSlowMotionFactor = 1.0f; + +// Scene +bool gSceneRunning = false; +float gTime = 0.0f; +float gLastTime = 0.0f; +bool gPause = false; +bool gDisableRendering = false; +bool gShowSplash = false; + +#ifdef USE_OPTIX +int gNumScenes = 9; +#else +int gNumScenes = 5; +#endif +int gSceneNr = 0; + +float gGroundY = 0.0f; +GLuint gGroundTexId = 0; + +GLuint gSplashScreenTexId = 0; +int gSplashWidth = 0; +int gSplashHeight = 0; +char gResourcePath[512] = "../../../externalIP/resources"; + +SampleViewerScene *gSampleScene = NULL; + +// Display +GLFontRenderer *gFontRenderer = NULL; + +int gMainHandle; +bool gHelp = false; +bool gDisplay = true; +char gDisplayString[512] = ""; +char gHelpString[2048] = ""; +char gDemoName[512] = ""; +float gFontSize = 0.02f; + +int gViewWidth = 0; +int gViewHeight = 0; +bool gShadows = false; +bool gWireframeMode = false; +bool gAdvancedRendering = true; +bool gDebugRendering = true; +bool gDrawGroundPlane = true; +PxVec3 gGroupPlanePose = PxVec3(0.f); +bool gDrawSkyBox = true; + +//bool gFXAAOn = true; +//bool gDoSSAO = true; +//bool gDoHDR = true; + +bool gFXAAOn = false; +bool gDoSSAO = true; +bool gDoHBAO = true; +bool gDoHDR = true; +bool gUseNormalMap = true; + +bool gDoDOF = false; + +// record movie +int gPixelBufferSize = 0; +GLbyte *gPixelBuffer = NULL; +bool gRecordBMP = false; +int gFrameNr = 0; +int gMaxFrameNr = 0; + +// Shading +int gNumShadows = 1; +bool gShowReflections = false; + +static const int gNumLights = 1; +PxVec3 gLightDirs[3]; +PxVec3 gLightPos[3]; +PxVec3 gBackLightDir; + +ShadowMap *gShadowMaps[4]; +ShaderShadow *gDefaultShader; +RenderTarget *gReflectedSceneTarget = NULL; + +int gZval = 15; +//FOMHelper* fom; +Shader* gDisplayTexProg; +Shader* gDisplayTexArrayProg; +Shader* gDisplaySplashProg = 0; +PxBounds3 sceneBounds; +PxBounds3 fluidBounds; +PxVec3 myDustColor; + +bool renderDust = true; + +#define MSAA_2x 2, 0, "MSAA_2x" +#define CSAA_4x 2, 4, "CSAA_4x" +#define CSAA_8x 4, 8, "CSAA_8x" +#define CSAA_8xQ 8, 8, "CSAA_8xQ" +#define CSAA_16x 4, 16, "CSAA_16x" +#define CSAA_16xQ 8, 16, "CSAA_16xQ" + +AABox* g_pAABox = 0; +int g_numAAModes = 5; +//int fullW = 1900; +//int fullH = 1200; + +int fullW = WINDOW_WIDTH; +int fullH = WINDOW_HEIGHT; +bool autoShoot = false; +bool gForceReloadShader = false; +bool gForceReloadDebugShader = false; + +using namespace std; + +struct SAAMode +{ + int ds; + int cs; + const char * name; +}; + +SAAMode g_aaModes[] = { + {MSAA_2x}, + {CSAA_8x}, + {CSAA_8xQ}, + {CSAA_16x}, + {CSAA_16xQ}, + { CSAA_4x } +}; + +bool doFXAA = false; +bool doAA = true; +int g_curAA = 0; +int g_curTech = 1; +float g_curSSSize = 1.7f; + +bool gShowRayCast = false; +bool fullScreen = false; + +// Camera +struct Camera { + void init() { + fov = 40.0f; + pos = PxVec3(0.0f, 30.0f, 20.0f); + forward = PxVec3(0.0f,0.0f,-1.0f); + right = PxVec3(1.0f,0.0f,0.0f); + + PxVec3 up(0, 1, 0); + + PxQuat qy(3.14/4.f, right); + forward = qy.rotate(forward).getNormalized(); + right = forward.cross(PxVec3(0, 1, 0)).getNormalized(); + + + speed = 0.15f; + rotate = false; + translate = false; + zoom = false; + + trackballMode = false; + trackballCenter = PxVec3(0.0f, 1.0f, 0.0f); + trackballRadius = 6.0f; + } + float fov; + PxVec3 pos, forward, right; + float speed; + bool rotate, translate, zoom; + bool trackballMode; + PxVec3 trackballCenter; + float trackballRadius; +}; + +Camera gCamera; + +// Mouse +int gMouseX = 0; +int gMouseY = 0; + +// keyboard +#define MAX_KEYS 256 +bool gKeys[MAX_KEYS]; + +// fps +float curFPS = 0.0f; +int gFrameCounter = 0; +float gPreviousTime = getCurrentTime(); + +volatile bool doneOneFrame = false; +volatile bool doneInit = false; +volatile bool doneRender = true; +volatile bool shouldEndThread = false; +volatile bool threadEnded = false; +volatile int simulateDoneS = 0; +bool renderEveryFrame = true; + +bool gParticlesTexOutdate = true; +bool gConvexTexOutdate = true; + + +//std::vector delCompoundList; + +SampleViewerGamepad sampleViewerGamepad; + +// ------------------------------------------------------------------------------------ +// This is needed to properly call cleanup routines when GLUT window is closed, as +// there is no close callback routine, and the default way simply calls exit(0) thus +// calling destructors w/o cleanups, leading to crash +// (see atexit function that sets exit callback) +// ------------------------------------------------------------------------------------ +bool gIsSampleCleanedUp = false; +void ReleaseSDKs(); +void CleanupSample(); +// ------------------------------------------------------------------------------------ + +physx::PxPvd* gPvd = NULL; +physx::PxPvdTransport* gTransport = NULL; +physx::PxPvdInstrumentationFlags gPvdFlags = physx::PxPvdInstrumentationFlag::eDEBUG; + +#include "PsString.h" +#include "PsThread.h" + +//class SampleViewerPVDHandler : public PxPvd +//{ +//public: +// +// void onPvdSendClassDescriptions(PVD::PvdConnection&) {} +// +// void onPvdConnected(PVD::PvdConnection& ) +// { +// //setup joint visualization. This gets piped to pvd. +// //gPxPhysics->getVisualDebugger()->setVisualDebuggerFlag(PxVisualDebuggerFlag::eTRANSMIT_CONSTRAINTS, true); +// //gPxPhysics->getVisualDebugger()->setVisualDebuggerFlag(PxVisualDebuggerFlag::eTRANSMIT_CONTACTS, true); +// //gPxPhysics->getVisualDebugger()->setVisualDebuggerFlag(PxVisualDebuggerFlag::eTRANSMIT_SCENEQUERIES, true); +// } +// +// void onPvdDisconnected(PVD::PvdConnection& conn) +// { +// conn.release(); +// } +//}; +// +//SampleViewerPVDHandler gPVDConnectionHandler; + +class SampleViewerErrorCallback : public PxErrorCallback +{ +public: + SampleViewerErrorCallback() {} + ~SampleViewerErrorCallback() {} + + virtual void reportError(PxErrorCode::Enum code, const char* message, const char* file, int line) + { + if (code == PxErrorCode::eDEBUG_INFO) + { + char buffer[1024]; + sprintf(buffer, "%s\n", message); + physx::shdfnd::printString(buffer); + } + else + { + const char* errorCode = NULL; + + switch (code) + { + case PxErrorCode::eINVALID_PARAMETER: + errorCode = "invalid parameter"; + break; + case PxErrorCode::eINVALID_OPERATION: + errorCode = "invalid operation"; + break; + case PxErrorCode::eOUT_OF_MEMORY: + errorCode = "out of memory"; + break; + case PxErrorCode::eDEBUG_INFO: + errorCode = "info"; + break; + case PxErrorCode::eDEBUG_WARNING: + errorCode = "warning"; + break; + case PxErrorCode::ePERF_WARNING: + errorCode = "performance warning"; + break; + case PxErrorCode::eABORT: + errorCode = "abort"; + break; + default: + errorCode = "unknown error"; + break; + } + + PX_ASSERT(errorCode); + if (errorCode) + { + char buffer[1024]; + sprintf(buffer, "%s (%d) : %s : %s\n", file, line, errorCode, message); + + physx::shdfnd::printString(buffer); + + // in debug builds halt execution for abort codes + PX_ASSERT(code != PxErrorCode::eABORT); + + // in release builds we also want to halt execution + // and make sure that the error message is flushed + while (code == PxErrorCode::eABORT) + { + physx::shdfnd::printString(buffer); + physx::shdfnd::Thread::sleep(1000); + } + } + } + } +}; + +SampleViewerErrorCallback gErrorCallback; +// ------------------------------------------------------------------------------------ +#include + +// ------------------------------------------------------------------------------------ +bool LoadTexture(const char *filename, GLuint &texId, bool createMipmaps, GLuint type = GL_TEXTURE_2D, int *width = NULL, int *height = NULL) +{ + char path[512]; + sprintf(path, "%s/%s", gResourcePath, filename); + + // read out image data + int len = strlen(path); + unsigned char* ptr = 0, *ptrBegin; + int w, h; + BmpLoaderBuffer loader; + CPPJPEGWrapper jpg; + if (strcmp(&path[len-4], ".jpg") == 0) { + // jpg + + if (!jpg.LoadJPEG(path, false)) { + printf("Error load jpg %s\n", path); + return false; + } + h = jpg.GetHeight(); + w = jpg.GetWidth(); + ptrBegin = ptr = jpg.GetData(); + } else { + // bmp + + if (!loader.loadFile(path)) { + fprintf(stderr, "Error loading bmp '%s'\n",path); + return false; + } + ptrBegin = ptr = loader.mRGB; + h = loader.mHeight; + w = loader.mWidth; + + } + + unsigned char *pColor = ptrBegin; + + int lineLen = 3*w; + GLubyte *buffer = new GLubyte[w*h*3]; + GLubyte *writePtr = &buffer[(h-1)*lineLen]; + + for (int i = 0; i < h; i++) { + GLubyte *writePtr = &buffer[i*lineLen]; + GLubyte *readPtr = &pColor[i*lineLen]; + for (int j = 0; j < w; j++) { + *writePtr++ = *readPtr++; + *writePtr++ = *readPtr++; + *writePtr++ = *readPtr++; + } + } + + // ------ generate texture -------------------------------- + + glGenTextures(1, &texId); + + glBindTexture(type, texId); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexParameteri(type, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(type, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(type, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(type, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexImage2D(type, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer); + if (createMipmaps) { + glTexParameteri(type, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + gluBuild2DMipmaps(type, GL_RGB, w, h, GL_RGB, GL_UNSIGNED_BYTE, buffer); + } + + delete[] buffer; + + if (width) + *width = w; + if (height) + *height = h; + return true; +} + +void displayTexture(GLuint tex) +{ + gDisplayTexProg->activate(); + gDisplayTexProg->bindTexture("tex", tex, GL_TEXTURE_2D, 0); + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f); + glTexCoord2f(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f); + glTexCoord2f(1.0f, 1.0f); glVertex2f( 1.0f, 1.0f); + glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f); + glEnd(); + gDisplayTexProg->deactivate(); +} +void displayTextureArray(GLuint tex, int slice) +{ + gDisplayTexArrayProg->activate(); + gDisplayTexArrayProg->bindTexture("tex", tex, GL_TEXTURE_2D_ARRAY_EXT, 0); + gDisplayTexArrayProg->setUniform1("slice", slice); + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f); + glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, -1.0f); + glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0f); + glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f); + glEnd(); + gDisplayTexArrayProg->deactivate(); +} +const char *textureRECTPS = STRINGIFY( +uniform sampler2DRect tex; +void main() +{ +gl_FragColor = texture2DRect(tex, gl_TexCoord[0].xy); \n +//gl_FragColor = vec4(1,0,0,1); +} +); +const char *texture2DArrayPS = STRINGIFY( + uniform sampler2DArray tex; +void main() +{ + gl_FragColor = texture2DArray(tex, vec3(gl_TexCoord[0].xy,0.0f)); \n + //gl_FragColor = vec4(1,0,0,1); +} +); + +void displaySplashScreen() +{ + float as = (float)gSplashWidth/gSplashHeight; + + float xv = 0.0f, yv = 0.0f; + float bs = gViewWidth / ((float)gViewHeight); + if (bs > as) { + // Too wide + // fit height + yv = 1.0f; + xv = (as*gViewHeight) / gViewWidth; + } else { + // Too Tall + xv = 1.0f; + yv = (gViewWidth/as) / gViewHeight; + } + + + gDisplaySplashProg->activate(); + gDisplaySplashProg->bindTexture("tex", gSplashScreenTexId, GL_TEXTURE_RECTANGLE_ARB, 0); + glBegin(GL_QUADS); + glTexCoord2f(0.0f, gSplashHeight); glVertex2f(-xv, -yv); + glTexCoord2f(gSplashWidth, gSplashHeight); glVertex2f( xv, -yv); + glTexCoord2f(gSplashWidth, 0.0f); glVertex2f( xv, yv); + glTexCoord2f(0.0f, 0.0f); glVertex2f(-xv, yv); + glEnd(); + gDisplaySplashProg->deactivate(); + +} + +// ------------------------------------------------------------------------------------ +void SaveFrameBuffer() +{ + char filename[256]; + sprintf(filename, SCREEN_DUMP_PATH, gFrameNr); + + int bufferSize = gViewWidth * gViewHeight * 3; + if (gPixelBufferSize != bufferSize) { + if (gPixelBuffer != NULL) + free(gPixelBuffer); + gPixelBuffer = (GLbyte *)malloc(bufferSize); + gPixelBufferSize = bufferSize; + } + + glReadBuffer(GL_BACK); + glReadPixels(0,0, gViewWidth, gViewHeight, GL_RGB, GL_UNSIGNED_BYTE, gPixelBuffer); + saveBmpRBG(filename, gViewWidth, gViewHeight, gPixelBuffer); +} + +// ------------------------------------------------------------------------------------ +void WaitForSim() +{ + if (gSceneRunning) + { + if (gSampleScene != NULL) + { + gSampleScene->syncAsynchronousWork(); + } + + PxU32 error; + gPxScene->fetchResults(true, &error); + + assert(error == 0); + gSceneRunning = false; + } +} + +// ------------------------------------------------------------------------------------ +PxFilterFlags contactReportFilterShader(PxFilterObjectAttributes attributes0, PxFilterData filterData0, + PxFilterObjectAttributes attributes1, PxFilterData filterData1, + PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize) +{ + PX_UNUSED((attributes0, attributes1, filterData0, filterData1, constantBlockSize, constantBlock)); + + // all initial and persisting reports for everything, with per-point data + pairFlags = PxPairFlag::eSOLVE_CONTACT | PxPairFlag::eDETECT_DISCRETE_CONTACT; + return PxFilterFlag::eDEFAULT; +} + +// ------------------------------------------------------------------------------------ + + +void CreateSampleViewerScene(); +void InitSampleViewerScene(); + +void RecreateSDKScenes() +{ + WaitForSim(); + + // physX + if (gPxScene != NULL) + gPxScene->release(); + + PxSceneDesc sceneDesc(gPxPhysics->getTolerancesScale()); + + sceneDesc.gravity = PxVec3(0.0f, -10.0f * gSlowMotionFactor * gSlowMotionFactor, 0.0f); // acceleration, factor squared + if (!gPxDispatcher) + gPxDispatcher = PxDefaultCpuDispatcherCreate(gNrWorkerThreads); + + if(!gCudaContextManager) + { + PxCudaContextManagerDesc cudaContextManagerDesc; + gCudaContextManager = PxCreateCudaContextManager(*gPxFoundation, cudaContextManagerDesc); + } + + + + sceneDesc.cpuDispatcher = gPxDispatcher; + sceneDesc.gpuDispatcher = gCudaContextManager->getGpuDispatcher(); + sceneDesc.filterShader = contactReportFilterShader; + sceneDesc.flags |= PxSceneFlag::eENABLE_PCM; + sceneDesc.flags |= PxSceneFlag::eENABLE_STABILIZATION; + if (gUseGrb) + { + sceneDesc.flags |= PxSceneFlag::eENABLE_GPU_DYNAMICS; + sceneDesc.broadPhaseType = PxBroadPhaseType::eGPU; + } + sceneDesc.flags |= PxSceneFlag::eSUPPRESS_EAGER_SCENE_QUERY_REFIT; + sceneDesc.gpuDynamicsConfig.contactStreamSize *= 2; + sceneDesc.gpuDynamicsConfig.forceStreamCapacity *= 2; + sceneDesc.gpuDynamicsConfig.patchStreamSize *= 2; + sceneDesc.gpuDynamicsConfig.tempBufferCapacity *= 2; + + gSampleScene->customizeSceneDesc(sceneDesc); + + gPxScene = gPxPhysics->createScene(sceneDesc); + + PxPvdSceneClient* pvdClient = gPxScene->getScenePvdClient(); + if (pvdClient) + { + pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, false); + pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, false); + pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, false); + } + + if(gPxScene == NULL) + { + printf("\nError: Unable to create a PhysX scene, exiting the sample.\n\n"); + exit(0); + } + + gCurrentUsingGrb = gUseGrb; +} + +//----------------------------------------------------------------------------- +bool InitPhysX() +{ + // SDK + gPxFoundation = PxCreateFoundation(PX_FOUNDATION_VERSION, gAllocator, gErrorCallback); + + gTransport = physx::PxDefaultPvdSocketTransportCreate("127.0.0.1", 5425, 10); + + gPvd = NULL; + +#if ENABLE_PVD + gPvd = physx::PxCreatePvd(*gPxFoundation); + //gPvd->connect(*gTransport, physx::PxPvdInstrumentationFlag::eALL); + gPvd->connect(*gTransport, physx::PxPvdInstrumentationFlag::ePROFILE); +#endif + + gPxPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gPxFoundation, PxTolerancesScale(), false, gPvd); + + + + if(gPxPhysics == NULL) + { + printf("\nPhysXSDK create error.\nUnable to initialize the PhysX SDK, exiting the sample.\n\n"); + return false; + } + PxCookingParams params(gPxPhysics->getTolerancesScale()); + params.buildGPUData = true; + gPxCooking = PxCreateCooking(PX_PHYSICS_VERSION, *gPxFoundation, params); + + if (gPxCooking == NULL) + { + printf("\nError: Unable to initialize the cooking library, exiting the sample.\n\n"); + return false; + } + + PxInitExtensions(*gPxPhysics, gPvd); + + UpdateTime(); + + return true; +} + +// ------------------------------------------------------------------------------------ +void ReleaseSDKs() +{ + WaitForSim(); + + if(gPxPhysics != NULL) + { + PxCloseExtensions(); + + gPxScene->release(); + gPxDispatcher->release(); + gPxPhysics->release(); + gPxCooking->release(); + if (gPvd) + { + gPvd->release(); + gPvd = NULL; + } + + gCudaContextManager->release(); + + gPxFoundation->release(); + gPxScene = NULL; + gPxDispatcher = NULL; + gPxPhysics = NULL; + gPxCooking = NULL; + gPxFoundation = NULL; + gCudaContextManager = NULL; + } +} + +// ------------------------------------------------------------------------------------ +PxReal UpdateTime() +{ + PxReal deltaTime; + gTime = timeGetTime()*0.001f; // Get current time in seconds + deltaTime = gTime - gLastTime; + gLastTime = gTime; + + return deltaTime; +} + +#define OVERLAP_SIM_AND_RENDER 1 + +// ------------------------------------------------------------------------------------ +static bool g_simulationRunning = false; +static PxReal g_simulationDT = 0.0f; +void BeginSimulation(void) +{ + assert(g_simulationRunning == false); + assert(g_simulationDT == 0.0f); + if(g_simulationRunning == false) + { + static float prevTime = getCurrentTime(); + float currTime = getCurrentTime(); + + float elapsedTime = currTime - prevTime; + + PxReal fSubsteps = elapsedTime / gTimeStepSize; + PxU32 iSubsteps = PxU32(fSubsteps); + PxU32 nbSubsteps = PxMax(1u, PxMin(iSubsteps, gMaxSubSteps)); + + prevTime += PxReal(iSubsteps)*gTimeStepSize; + + for (PxU32 a = 0; a < nbSubsteps; ++a) + { + + +#if OVERLAP_SIM_AND_RENDER + if (gSceneRunning) + { + //fetchResult + + WaitForSim(); + if (gSampleScene != NULL) + { + gSampleScene->postSim(gTimeStepSize); + } + } +#endif + + if (gForceSceneRecreate) + { + if (--gCountdownToRecereate) + { + CreateSampleViewerScene(); + RecreateSDKScenes(); + InitSampleViewerScene(); + + gForceSceneRecreate = false; + } + } + else if (gUseGrb != gCurrentUsingGrb) + { + PxScene* oldScene = gPxScene; + gPxScene = NULL; + + RecreateSDKScenes(); //Create the PxScene... + + const PxU32 nbRigidStatics = oldScene->getNbActors(PxActorTypeFlag::eRIGID_STATIC); + const PxU32 nbRigidDynamics = oldScene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC); + + Ps::Array actors(nbRigidStatics + nbRigidDynamics); + + oldScene->getActors(PxActorTypeFlag::eRIGID_STATIC, actors.begin(), nbRigidStatics); + oldScene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC, actors.begin() + nbRigidStatics, nbRigidDynamics); + + + for (PxU32 a = 0; a < actors.size(); ++a) + { + oldScene->removeActor(*actors[a],false); + //gPxScene->addActor(*actors[a]); + } + + for (PxU32 a = 0; a < actors.size(); ++a) + { + //oldScene->removeActor(*actors[a]); + gPxScene->addActor(*actors[a]); + } + + oldScene->release(); + + gSampleScene->setScene(gPxScene); + + gCurrentUsingGrb = gUseGrb; + } + + { + if (gSampleScene != NULL) + gSampleScene->preSim(gTimeStepSize); + + gPxScene->simulate(gTimeStepSize); + + if (gSampleScene != NULL) + gSampleScene->duringSim(gTimeStepSize); + + gSceneRunning = true; + + g_simulationDT = gTimeStepSize; + g_simulationRunning = true; + } + +#if !OVERLAP_SIM_AND_RENDER + //if((a + 1) < nbSubsteps) + { + WaitForSim(); + if (gSampleScene != NULL) + { + gSampleScene->postSim(gTimeStepSize); + } + } +#endif + } + + + } +} + +// ------------------------------------------------------------------------------------ +void EndSimulation(void) +{ + assert(g_simulationRunning == true); + assert(g_simulationDT != 0.0f); + if(g_simulationRunning == true) + { + PxReal dt = g_simulationDT; + +#if !OVERLAP_SIM_AND_RENDER + if (gSceneRunning) + { + //fetchResult + WaitForSim(); + if (gSampleScene != NULL) + { + gSampleScene->postSim(gTimeStepSize); + } + } +#endif + + ++gPhysicsFrameNumber; + + g_simulationDT = 0.0f; + g_simulationRunning = false; + + gParticlesTexOutdate = true; + gConvexTexOutdate = true; + } +} + +// ------------------------------------------------------------------------------------ +void RunPhysics() +{ + BeginSimulation(); + EndSimulation(); +} + +// ------------------------------------------------------------------------------------ + +void DisplayText() +{ + const char* aoString = gDoSSAO ? (gDoHBAO ? "(HBAO+)" : "(SSAO)"): "(NOAO)"; + const char* normalString = gUseNormalMap ? "(NormalMap)" : "(NormalsFromDepth)"; + sprintf(gDisplayString, ""); + if (gDisplay) + sprintf(gDisplayString, "FPS = %0.2f\n Scene %i: %s %s%s %s %s", curFPS, gSceneNr + 1, gDemoName, gUseGrb ? "(GPU)" : "(CPU)", gHelp ? gHelpString : "", aoString, normalString); + + + float y = 0.95f; + int len = strlen(gDisplayString); + len = (len < 1024)?len:1023; + int start = 0; + char textBuffer[1024]; + for(int i=0;iprint(0.01, y, gFontSize, textBuffer); + y -= 0.035f; + start = offset+1; + } + } +} + +// ------------------------------------------------------------------------------------ +void SetHelpString() +{ + //char tempString[256]; + sprintf(gHelpString, "\nGeneral:\n"); + //sprintf(tempString, " 1-%d: choose scene\n", gNumScenes); + + strcat(gHelpString, " F10: Reset scene\n"); + strcat(gHelpString, " 1-5 or F10: Reset scene\n"); + strcat(gHelpString, " F5: Toggle between CPU and GPU simulation\n"); + strcat(gHelpString, " p: Pause\n"); + strcat(gHelpString, " o: Single step\n"); + if (gSceneNr == 2) + { + strcat(gHelpString, " F7: Detach/reattach camera\n"); + strcat(gHelpString, " w,a,s,d,q,e: Drive car or move camera if camera is detached\n"); + } + + if (gSceneNr == 3) + { + strcat(gHelpString, " k: Spawn walker at mouse location\n"); + } + strcat(gHelpString, " w,a,s,d,q,e: Camera\n"); + strcat(gHelpString, " f: Toggle full screen mode\n"); + + strcat(gHelpString, " F1: Toggle help\n"); + + strcat(gHelpString, " F4: Change weapon: "); + if (gSampleScene != NULL) + strcat(gHelpString, gSampleScene->getWeaponName().c_str()); + strcat(gHelpString, "\n"); + + strcat(gHelpString, " Shift-mouse: Drag objects\n"); + strcat(gHelpString, " Space: Shoot\n"); + if (gSceneNr == 0) + strcat(gHelpString, " b: Attack tower with random shapes\n"); +} + +// ------------------------------------------------------------------------------------ +void ProcessKeys() +{ + // Process keys + for (int i = 0; i < MAX_KEYS; i++) + { + if (!gKeys[i]) { continue; } + + PxVec3 up; + up = PxVec3(0,1,0); + PxVec3 &pos = gCamera.trackballMode ? gCamera.trackballCenter : gCamera.pos; + + + if (!gSampleScene->isCameraDisable()) + { + if (gCamera.trackballMode) { + switch (i) + { + // Camera controls + case 'W': + case 'w':{ + gCamera.trackballRadius -= gCamera.speed; + if (gCamera.trackballRadius < 0.1f) gCamera.trackballRadius = 0.1f; + break; + } + case 'S': + case 's':{ gCamera.trackballRadius += gCamera.speed; break; } + case 'E': + case 'e':{ pos -= up * gCamera.speed; break; } + case 'Q': + case 'q':{ pos += up * gCamera.speed; break; } + } + } + else { + switch (i) + { + // Camera controls + case 'W': + case 'w':{ pos += gCamera.forward * gCamera.speed; break; } + case 'S': + case 's':{ pos -= gCamera.forward * gCamera.speed; break; } + case 'A': + case 'a':{ pos -= gCamera.right * gCamera.speed; break; } + case 'D': + case 'd':{ pos += gCamera.right * gCamera.speed; break; } + case 'E': + case 'e':{ pos -= up * gCamera.speed; break; } + case 'Q': + case 'q':{ pos += up * gCamera.speed; break; } + } + } + } + + } +} +float XXX = 0.0f; + float modelMatrix[16]; + float projMatrix[16]; +// ------------------------------------------------------------------------------------ + +void SetupCamera(bool mirrored = false) +{ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + float aspectRatio = ((float)glutGet(GLUT_WINDOW_WIDTH)/(float)glutGet(GLUT_WINDOW_HEIGHT)); + gluPerspective(gCamera.fov, aspectRatio, zNear, zFar); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + if (gCamera.trackballMode) { + gCamera.trackballCenter.x = 0.0f; + gCamera.trackballCenter.z = 0.0f; + gCamera.pos = gCamera.trackballCenter - gCamera.forward * gCamera.trackballRadius; + } + + + gSampleScene->getCamera(gCamera.pos, gCamera.forward); + + PxVec3 pos = gCamera.pos; + PxVec3 dir = gCamera.forward; + PxVec3 apos = gCamera.pos + dir; + + + gluLookAt(pos.x, pos.y, pos.z, pos.x + dir.x, pos.y + dir.y, pos.z + dir.z, 0.0f, 1.0f, 0.0f); + + if (mirrored) { + PxTransform trans; + + PxVec3 waterN(0.0f, 1.0f, 0.0f); + PxVec3 waterP(0.0f,gGroundY,0.0f); + float QQQ = 0.00f; + waterP.y += QQQ; + float np2 = 2.0f*waterN.dot(waterP); + + PxVec3 r0 = PxVec3(1.0f, 0.0f, 0.0f) - 2*waterN.x*waterN; + PxVec3 r1 = PxVec3(0.0f, 1.0f, 0.0f) - 2*waterN.y*waterN; + PxVec3 r2 = PxVec3(0.0f, 0.0f, 1.0f) - 2*waterN.z*waterN; + PxVec3 t = np2*waterN; + + float matGL[16] = { + r0.x, r1.x, r2.x, 0.0f, + r0.y, r1.y, r2.y, 0.0f, + r0.z, r1.z, r2.z, 0.0f, + t.x, t.y, t.z, 1.0f}; + + glMultMatrixf(matGL); + + } + + + glGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix); + glGetFloatv(GL_PROJECTION_MATRIX, projMatrix); + + gDefaultShader->updateCamera(modelMatrix, projMatrix); + if (gSampleScene != NULL) { + for (int i = 0; i < (int)gSampleScene->getShaders().size(); i++) + gSampleScene->getShaders()[i]->updateCamera(modelMatrix, projMatrix); + gSampleScene->setCamera(gCamera.pos, gCamera.forward, PxVec3(0,1,0), gCamera.fov); + } + + gCamera.right = gCamera.forward.cross(PxVec3(0,1,0)).getNormalized(); + gCamera.forward.normalize(); + +} + +// ------------------------------------------------------------------------------------ +void RenderObjects(bool useShader, bool reflectedOnly) +{ + ShaderMaterial mat; + mat.init(); + + // ground plane + if (!reflectedOnly && gDrawGroundPlane) + { + if (useShader) { + mat.init(); + mat.reflectionCoeff = 0.2f; + if (gGroundTexId > 0) { + mat.texId = gGroundTexId; + } + } + if (useShader) + gDefaultShader->activate(mat); + + const float size = 1000.0f; + const float y = -0.002f; + + + PxVec3 center = gGroupPlanePose; + PxVec3 p0 = center + PxVec3(-size, y, -size); + PxVec3 p1 = center + PxVec3( size, y, -size); + PxVec3 p2 = center + PxVec3( size, y, size); + PxVec3 p3 = center + PxVec3(-size, y, size); + + float texScale = 300.0f; + PxVec3 t0(0.0f, 0.0f, 0.0f); + PxVec3 t1(texScale, 0.0f, 0.0f); + PxVec3 t2(texScale, texScale, 0.0f); + PxVec3 t3(0.0f, texScale, 0.0f); + + glBegin(GL_TRIANGLES); + glNormal3f(0.0f, 1.0f, 0.0f); + glTexCoord2f(t0.x, t0.y); glVertex3f(p0.x, p0.y, p0.z); + glTexCoord2f(t2.x, t2.y); glVertex3f(p2.x, p2.y, p2.z); + glTexCoord2f(t1.x, t1.y); glVertex3f(p1.x, p1.y, p1.z); + + glTexCoord2f(t0.x, t0.y); glVertex3f(p0.x, p0.y, p0.z); + glTexCoord2f(t3.x, t3.y); glVertex3f(p3.x, p3.y, p3.z); + glTexCoord2f(t2.x, t2.y); glVertex3f(p2.x, p2.y, p2.z); + glEnd(); + if (useShader) + gDefaultShader->deactivate(); + } + + if (gSampleScene != NULL) + gSampleScene->render(useShader); + +/* + glDisable(GL_LIGHTING); + + + glBindBuffer(GL_ARRAY_BUFFER, gFluidSim.mistPS->glVB[currentBufMultiGPU]); + glVertexPointer(3, GL_FLOAT, sizeof(CUGLParticleInfo), (void*)0); + glEnableClientState(GL_VERTEX_ARRAY); + glColor3f(1.0f,1.0f,1.0f); + glDrawArrays(GL_POINTS, 0, gFluidSim.mistPS->numGLPars[currentBufMultiGPU]); + + glDisableClientState(GL_VERTEX_ARRAY); + glBindBuffer(GL_ARRAY_BUFFER, 0); + */ + +//glDisable(GL_LIGHTING); + + if (gShowRayCast) { + + glDisable(GL_LIGHTING); + SimScene* simScene = ((SceneKapla*)gSampleScene)->getSimScene(); + PxScene* scene = simScene->getScene(); + + PxVec3 start(-30.0f,0.0f,-30.0f); + PxVec3 xdir(1.0f,0.0f,0.0f); + PxVec3 zdir(0.0f,0.0f,1.0f); + PxVec3 castDir(0.0f, -1.0f, 0.0f); + PxVec3 castPos(0.0f, 100.0f, 0.0f); + float dist = 300.0f; + float dx = 0.3f; + int nx = 200; + int nz = 200; + + + glPointSize(10.0f); + glBegin(GL_POINTS); + + PxHitFlags ff = PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eDISTANCE; + PxRaycastBuffer buf1; + PxRaycastHit hit; + for (int i = 0; i < nz; i++) { + for (int j = 0; j < nx; j++) { + PxVec3 startP = start + xdir*dx*j + zdir*dx*i + castPos; + scene->raycast(startP, castDir, dist, buf1, ff); + hit = buf1.block; + if (buf1.hasBlock) { + PxVec3 pos = startP + hit.distance * castDir; + glColor3f(1.0f,0.0f,0.0f); + glVertex3fv(&pos.x); + } else { + PxVec3 pos = startP; + pos.y = 0.0f; + glColor3f(0.0f,1.0f,0.0f); + glVertex3fv(&pos.x); + + } + + // scene->raycastSingle() + + } + } + + glEnd(); + glEnable(GL_LIGHTING); + } +} + +// ------------------------------------------------------------------------------------ +void RenderShadowCasters() +{ + RenderObjects(false, true); +} + +inline void RenderDepthNormalInline(bool renderNormals){ + if(renderNormals) + ShaderShadow::renderMode = ShaderShadow::RENDER_DEPTH_NORMAL; + else + ShaderShadow::renderMode = ShaderShadow::RENDER_DEPTH; + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + if (gCamera.trackballMode) { + gCamera.trackballCenter.x = 0.0f; + gCamera.trackballCenter.z = 0.0f; + gCamera.pos = gCamera.trackballCenter - gCamera.forward * gCamera.trackballRadius; + } + + PxVec3 pos = gCamera.pos; + PxVec3 dir = gCamera.forward; + PxVec3 apos = gCamera.pos + dir; + gluLookAt(pos.x, pos.y, pos.z, pos.x + dir.x, pos.y + dir.y, pos.z + dir.z, 0.0f, 1.0f, 0.0f); + RenderObjects(true, false); + + ShaderShadow::renderMode = ShaderShadow::RENDER_COLOR; + +} + +void RenderDepthNormal() +{ + RenderDepthNormalInline(true); +} + +void RenderDepthOnly() +{ + RenderDepthNormalInline(false); +} + +// ------------------------------------------------------------------------------------ +void RenderScene() +{ + // shadows + SetupCamera(false); + + int numShadows = gNumShadows; + bool showReflections = gShowReflections; + if (SampleViewerScene::getRenderType() == SampleViewerScene::rtOPTIX) { + numShadows = 0; + showReflections = false; + } + + if (numShadows > 0) { + ShaderShadow::renderMode = ShaderShadow::RENDER_DEPTH; + for (int i = 0; i < gNumLights; i++) { + if (gShadowMaps[i] == NULL) + //gShadowMaps[i] = new ShadowMap(gViewWidth, gViewHeight, gCamera.fov, i,12000); + //gShadowMaps[i] = new ShadowMap(gViewWidth, gViewHeight, gCamera.fov, i, 12000); + gShadowMaps[i] = new ShadowMap(gViewWidth, gViewHeight, gCamera.fov, i, 6144); + + gDefaultShader->setShadowMap(i, gShadowMaps[i]); + if (gSampleScene != NULL) { + for (int j = 0; j < (int)gSampleScene->getShaders().size(); j++) + gSampleScene->getShaders()[j]->setShadowMap(i, gShadowMaps[i]); + } + if (i > numShadows) + continue; + + + if (gShadowMaps[i] != NULL) + gShadowMaps[i]->makeShadowMap(gCamera.pos, gCamera.forward, gLightDirs[i], + shadowClipNear, shadowClipFar, &RenderShadowCasters); + } + ShaderShadow::renderMode = ShaderShadow::RENDER_COLOR; + } + + for (int i = 0; i < gNumLights; i++) + gDefaultShader->setSpotLight(i, gLightPos[i], gLightDirs[i]); + gDefaultShader->setBackLightDir(gBackLightDir); + gDefaultShader->setNumShadows(numShadows); + gDefaultShader->setShowReflection(showReflections); + + if (gSampleScene != NULL) { + for (int i = 0; i < (int)gSampleScene->getShaders().size(); i++) { + ShaderShadow *s = gSampleScene->getShaders()[i]; + for (int j = 0; j < gNumLights; j++) + s->setSpotLight(j, gLightPos[j], gLightDirs[j]); + s->setBackLightDir(gBackLightDir); + s->setNumShadows(numShadows); + s->setShowReflection(showReflections); + } + } + + // reflection + if (showReflections) { + + int reflectWidth = gViewWidth; + int reflectHeight = gViewHeight; + + if (doAA) { + reflectWidth = g_pAABox->getBufW(); + reflectHeight = g_pAABox->getBufH(); + } + if (gReflectedSceneTarget == NULL) { + + gReflectedSceneTarget = new RenderTarget(reflectWidth, reflectHeight); + gReflectedSceneTarget->beginCapture(); + glViewport(0, 0, reflectWidth, reflectHeight); + gReflectedSceneTarget->endCapture(); + + gDefaultShader->setReflectionTexId(gReflectedSceneTarget->getColorTexId()); + if (gSampleScene != NULL) { + for (int i = 0; i < (int)gSampleScene->getShaders().size(); i++) + gSampleScene->getShaders()[i]->setReflectionTexId(gReflectedSceneTarget->getColorTexId()); + } + } + + glViewport(0, 0, reflectWidth, reflectHeight); + gReflectedSceneTarget->beginCapture(); + + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); +// glClear(GL_DEPTH_BUFFER_BIT); // todo: why is this faster? + + GLdouble clipEq[4]; + clipEq[0] = 0.0f; + clipEq[1] = -1.0f; + clipEq[2] = 0.0f; + clipEq[3] = gGroundY; + glEnable(GL_CLIP_PLANE0); + glClipPlane(GL_CLIP_PLANE0, clipEq); + + SetupCamera(true); + RenderObjects(true, true); + + glDisable(GL_CLIP_PLANE0); + gReflectedSceneTarget->endCapture(); + } + glViewport(0, 0, gViewWidth, gViewHeight); + + SetupCamera(); + + bool useFXAA = doFXAA && gFXAAOn; + + if (gDoHDR) + gHDRHelper->beginHDR(true); + else + { + if (useFXAA) + gFXAAHelper->StartFXAA(); + } + + if (doAA) { + if (gDoHDR) { + g_pAABox->oldFbo = gHDRHelper->mHDRFbo; + + } + g_pAABox->Activate(0,0); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + + + RenderObjects(true, false); + + //glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + if (gDoSSAO) { + int oldFbo = (doAA)? (g_pAABox->fbms ? g_pAABox->fbms : g_pAABox->fb) : 0; + + if (useFXAA) oldFbo = gFXAAHelper->FBO; + if (gDoHDR) { + if (!doAA) { + oldFbo = gHDRHelper->mHDRFbo; + } + } + + if (gDoHBAO) + gHBAOHelper->renderAO(gUseNormalMap ? RenderDepthNormal : RenderDepthOnly, oldFbo, gUseNormalMap); + else + gSSAOHelper->DoSSAO(RenderDepthNormal, oldFbo); + } + + if (doAA) {g_pAABox->Deactivate();} + if (doAA) g_pAABox->Draw(g_curTech); + + if (gDoHDR) + { + if (useFXAA) gFXAAHelper->StartFXAA(); + if (useFXAA) { + gHDRHelper->DoHDR(gFXAAHelper->FBO, gDoDOF); + } else { + gHDRHelper->DoHDR(0, gDoDOF); + } + } + + if (useFXAA) + gFXAAHelper->EndFXAA(0); +} + +// ------------------------------------------------------------------------------------ +void RenderCallback() +{ + if (gForceReloadShader) { + SceneKapla* scene = (SceneKapla*) gSampleScene; + scene->mSimSceneShader->loadShaders((string(gResourcePath) + string("\\shaders\\scene_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\scene_fs.cpp")).c_str()); + gForceReloadShader = false; + } + if (gForceReloadDebugShader) { + gDisplayTexArrayProg->loadShaders((string(gResourcePath) + string("\\shaders\\passthrough_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\shadowdebug_fs.cpp")).c_str()); + gDefaultShader->loadShaders((string(gResourcePath) + string("\\shaders\\default_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\default_fs.cpp")).c_str()); + gHDRHelper->mShaderDOF.loadShaders((string(gResourcePath) + string("\\shaders\\dof_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\dof_fs.cpp")).c_str()); + gHDRHelper->mShaderBloomH.loadShaders((string(gResourcePath) + string("\\shaders\\dof_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\bloomH_fs.cpp")).c_str()); + gHDRHelper->mShaderBloomV.loadShaders((string(gResourcePath) + string("\\shaders\\dof_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\bloomV_fs.cpp")).c_str()); + gSSAOHelper->SSAOFilterH.loadShaders((string(gResourcePath) + string("\\shaders\\filterv_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\filterh_fs.cpp")).c_str()); + gSSAOHelper->SSAOFilterV.loadShaders((string(gResourcePath) + string("\\shaders\\filterv_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\filterv_fs.cpp")).c_str()); + + SceneKapla* scene = (SceneKapla*)gSampleScene; + if (!scene->mSimSceneShader->loadShaders((string(gResourcePath) + string("\\shaders\\combine_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\combine_fs.cpp")).c_str())) { + printf("Can't load shader\n"); + } + gForceReloadDebugShader = false; + + + } + + static float first_frame_time = getCurrentTime(); + + ProcessKeys(); + if (gDisableRendering) + { + if(!gPause) + { + BeginSimulation(); + EndSimulation(); + } + } + else + { + if (!gPause) + BeginSimulation(); + + // Clear buffers + // glClearColor(0.52f, 0.60f, 0.71f, 1.0f); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (SampleViewerScene::getRenderType() == SampleViewerScene::rtOPTIX) { + gSampleScene->render(true); + SetupCamera(); + } else { + RenderScene(); + } + + DisplayText(); + + if(gSampleScene) + { + sampleViewerGamepad.processGamepads(*gSampleScene); + } + + glutSwapBuffers(); + glutReportErrors(); + + if (!gPause) + EndSimulation(); + + if (gRecordBMP) + SaveFrameBuffer(); + } + + gFrameNr++; // global frame nr + gFrameCounter++; // FPS + + if (gMaxFrameNr > 0) { // benchmark mode + if (gFrameNr >= gMaxFrameNr) { + printf("Benchmark done %d frames: %g seconds.\n", + gMaxFrameNr, getCurrentTime() - first_frame_time ); + SampleViewerScene::cleanupStaticResources(); + exit(0); + } + } + + if (gShot) { + } + + +} + +// ------------------------------------------------------------------------------------ +void ReshapeCallback(int width, int height) +{ + gViewWidth = width; + gViewHeight = height; + glViewport(0, 0, width, height); + + if (gDoHDR) + { + gHDRHelper->Resize(width, height); + } + + if (doAA) { + if(g_pAABox) delete g_pAABox; + g_pAABox = new AABox(gResourcePath); + g_pAABox->Initialize(width, height, g_curSSSize, g_aaModes[g_curAA].ds, g_aaModes[g_curAA].cs); + gSSAOHelper->Resize(g_pAABox->bufw, g_pAABox->bufh); + gHBAOHelper->resize(g_pAABox->bufw, g_pAABox->bufh, width, height); + } else { + gSSAOHelper->Resize(width, height); + gHBAOHelper->resize(width, height, width, height); + } + if (doFXAA) { + gFXAAHelper->Resize(width, height); + } + +} + +// ------------------------------------------------------------------------------------ +void IdleCallback() +{ + glutPostRedisplay(); + + float time = getCurrentTime(); + float elapsedTime = time - gPreviousTime; + + if (elapsedTime > 1.0f) { + char title[30]; + curFPS = (float)gFrameCounter / elapsedTime; + // + sprintf(title, "GRB Demo"); + glutSetWindowTitle(title); + gPreviousTime = time; + gFrameCounter = 0; + } + getElapsedTime(); +} + + +void CreateSampleViewerScene() +{ + if (gSampleScene != NULL) + delete gSampleScene; + gSampleScene = NULL; + + if (gMaxFrameNr > 0) { // benchmark mode + gPause = false; + } + else { + gPause = false; + } + + + float sceneSize = 20.0f; + sceneBounds.minimum = PxVec3(-sceneSize, 0.0f, -sceneSize); + sceneBounds.maximum = PxVec3(sceneSize, sceneSize, sceneSize); + + float fluidSize = 5.0f; + + + //printf("Scene B is %f %f %f --- %f %f %f\n", sceneBounds.minimum.x, sceneBounds.minimum.y, sceneBounds.minimum.z, + // sceneBounds.maximum.x, sceneBounds.maximum.y, sceneBounds.maximum.z); + //gForceReloadDebugShader = true; + PxVec3 target(0.0f, 0.0f, 0.0f); + g_fogStart = 50.0f; + g_fogEnd = 150.0f; + shadowClipNear = 0.2f; + shadowClipFar = 100.0f; + + DEFAULT_SOLVER_ITERATIONS = 8; + + g_shadowAdd = -0.001f; + + switch (gSceneNr) { + case 0: + { + gSampleScene = new SceneKaplaTower(gPxPhysics, gPxCooking, gUseGrb, gDefaultShader, gResourcePath, gSlowMotionFactor); + gLightPos[0] = PxVec3(sceneBounds.maximum.x, sceneBounds.maximum.y*3.0f, sceneBounds.maximum.z*2.f)*5.0f; + //g_shadowAdd = 0.f;// -0.004054f; + + sprintf(gDemoName, "GRB Kapla Tower"); + break; + } + case 1: + { + gSampleScene = new SceneKaplaArena(gPxPhysics, gPxCooking, gUseGrb, gDefaultShader, gResourcePath, gSlowMotionFactor); + gLightPos[0] = PxVec3(sceneBounds.maximum.x, sceneBounds.maximum.y*3.0f, sceneBounds.maximum.z)*5.0f; + //g_shadowAdd = -0.003; + //g_shadowAdd = 0.f; + sprintf(gDemoName, "GRB Kapla Arena"); + break; + } + case 2: + { + gSampleScene = new SceneVehicle(gPxPhysics, gPxCooking, gUseGrb, gDefaultShader, gResourcePath, gSlowMotionFactor); + gLightPos[0] = PxVec3(sceneBounds.maximum.x, sceneBounds.maximum.y*3.0f, -sceneBounds.maximum.z)*5.0f; + //g_shadowAdd = -0.003; + //g_shadowAdd = -0.001891; + //g_shadowAdd = 0.f; + sprintf(gDemoName, "GRB Vehicle Demo"); + break; + } + case 3: + { + //DEFAULT_SOLVER_ITERATIONS = 4; + gSampleScene = new SceneCrab(gPxPhysics, gPxCooking, gUseGrb, gDefaultShader, gResourcePath, gSlowMotionFactor); + gLightPos[0] = PxVec3(-sceneBounds.maximum.x, sceneBounds.maximum.y*8.0f, sceneBounds.maximum.z)*8.0f; + //g_shadowAdd = -0.001891; + //g_shadowAdd = 0.f; + g_fogStart = 150.0f; + g_fogEnd = 350.0f; + //shadowClipFar = 100.0f; + sprintf(gDemoName, "GRB Walkers Demo "); + + break; + } + default: + { + //DEFAULT_SOLVER_ITERATIONS = 4; + //g_shadowAdd = -0.004054f; + //g_shadowAdd = 0.f; + //shadowClipFar = 130.0f; + gLightPos[0] = PxVec3(0.f, 25.f, 150.f); + gSampleScene = new SceneRagdollWashingMachine(gPxPhysics, gPxCooking, gUseGrb, gDefaultShader, gResourcePath, gSlowMotionFactor); + sprintf(gDemoName, "GRB Ragdoll Demo "); + break; + } + } + + SceneKapla* scene = (SceneKapla*)gSampleScene; + + if (!scene->mSimSceneShader->loadShaders((string(gResourcePath) + string("\\shaders\\combine_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\combine_fs.cpp")).c_str())) + { + printf("Can't load shader\n"); + } + + gSampleScene->getInitialCamera(gCamera.pos, gCamera.forward); + float fogColor[4] = { 0, 0, 0, 1 }; + glFogf(GL_FOG_DENSITY, 0.0009f); + glFogf(GL_FOG_START, g_fogStart); + glFogf(GL_FOG_END, g_fogEnd); + glFogfv(GL_FOG_COLOR, fogColor); + + gLightDirs[0] = gLightPos[0] - target; + gLightDirs[0].normalize(); + + if (gSceneNr == 4) + { + gLightDirs[0] = PxVec3(0.f, 0.2f, 1.f).getNormalized(); + } + + gLightPos[1] = PxVec3(sceneBounds.minimum.x, sceneBounds.maximum.y, sceneBounds.minimum.z); + gLightDirs[1] = gLightPos[1] - target; + gLightDirs[1].normalize(); + + gLightPos[2] = PxVec3((sceneBounds.minimum.x + sceneBounds.maximum.x) * 0.5f, sceneBounds.maximum.y, sceneBounds.minimum.z); + gLightDirs[2] = gLightPos[2] - target; + gLightDirs[2].normalize(); + + gBackLightDir = PxVec3(0.8f, -1.0f, -1.2f); + gBackLightDir.normalize(); + + myDustColor = ((SceneKapla*)gSampleScene)->getSimSceneShader()->getDustColor(); + SetHelpString(); + +} + +// ------------------------------------------------------------------------------------ +void InitSampleViewerScene() +{ + gSampleScene->onInit(gPxScene); +} + +void InitGlutCallbacks(bool, int, int); + +//----------------------------------------------------------------------------- +void ToggleFullscreen() +{ + static int window[4] = {-1, -1, -1, -1}; + + if ( window[0] == -1) { // We are in non-fullscreen mode + window[0] = glutGet(GLUT_WINDOW_WIDTH); + window[1] = glutGet(GLUT_WINDOW_HEIGHT); + window[2] = glutGet(GLUT_WINDOW_X); + window[3] = glutGet(GLUT_WINDOW_Y); + glutFullScreen(); + } + else + { // We are in fullscreen mode + glutPositionWindow( window[2], window[3] ); + glutReshapeWindow( window[0], window[1] ); + window[0] = -1; + } + + + + glutPostRedisplay(); +} + + +// ------------------------------------------------------------------------------------ +void KeyboardCallback(unsigned char key, int x, int y) +{ + if (key != 'p' && key != 'w' && key != 'a' && key != 's' && key != 'd' && key != 'q' && key != 'e' && key != 'x' && key != 'v' + && key != 'u' && key != 'i' && key != 'k' && key != 'y' && key != 'b' && key != 'c' && key != 'h' && key != 'H' && key != 'n') + gPause = false; + + if (key == ' ') { + gShot = true; + } + + gKeys[key] = true; + + if ('1' <= key && key <= '0' + gNumScenes) + { + gSceneNr = key - '0' - 1; + + WaitForSim(); + + if (gSampleScene) + delete gSampleScene; + gSampleScene = NULL; + + CreateSampleViewerScene(); + RecreateSDKScenes(); + + InitSampleViewerScene(); + + } + + switch (key) + { + case 'f' : ToggleFullscreen(); break; + + case 27 : { + CleanupSample(); + exit(0); + } break; + case 'p': { gPause = !gPause; UpdateTime(); break; } + case 'o': { if (!gPause) gPause = true; RunPhysics(); glutPostRedisplay(); break; } + case 'h': { gDoSSAO = !gDoSSAO; break; } + case 'H': { gDoHBAO = !gDoHBAO; break; } + //case 'n': { gUseNormalMap = !gUseNormalMap; break; } + + default: ; + } + + if (gSampleScene != NULL) + gSampleScene->handleKeyDown(key, x, y); +} + +void CleanupSample() +{ + if (gIsSampleCleanedUp) + return; + + WaitForSim(); + + if (gSampleScene != NULL) { + delete gSampleScene; + gSampleScene = 0; + } + SampleViewerScene::cleanupStaticResources(); + ReleaseSDKs(); + + glutDestroyWindow(gMainHandle); + + gIsSampleCleanedUp = true; +} + +// ------------------------------------------------------------------------------------ + +void KeyboardUpCallback(unsigned char key, int x, int y) +{ + gKeys[key] = false; + if (gSampleScene != NULL) + gSampleScene->handleKeyUp(key, x, y); +} + +// ------------------------------------------------------------------------------------ + +void SpecialCallback(int key, int x, int y) +{ + switch (key) + { + // Reset PhysX + case GLUT_KEY_F1: + gHelp = !gHelp; + break; + case GLUT_KEY_F2: + gDisplay = !gDisplay; + break; + + case GLUT_KEY_F10: + { + WaitForSim(); + + if (gSampleScene) + delete gSampleScene; + gSampleScene = NULL; + + CreateSampleViewerScene(); + RecreateSDKScenes(); + + InitSampleViewerScene(); + return; + } + case GLUT_KEY_F5: + { + gUseGrb = !gUseGrb; + } + } + if (gSampleScene != NULL) + gSampleScene->handleSpecialKey(key, x, y); + + SetHelpString(); +} + +// ------------------------------------------------------------------------------------ +void MouseCallback(int button, int state, int x, int y) +{ + if (button != GLUT_LEFT_BUTTON || glutGetModifiers() != 0) + gPause = false; + + gMouseX = x; + gMouseY = y; + + if (!(glutGetModifiers() & GLUT_ACTIVE_SHIFT)) { + + if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) + { + gCamera.zoom = true; + } + else if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) + { + gCamera.rotate = true; + } + else if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) + { + gCamera.translate = true; + } + } + if (state == GLUT_UP) + { + gCamera.rotate = false; + gCamera.translate = false; + gCamera.zoom = false; + } + + if (gSampleScene != NULL) + gSampleScene->handleMouseButton(button, state, x, y); +} + +// ------------------------------------------------------------------------------------ + +void MotionCallback(int x, int y) +{ + + int dx = gMouseX - x; + int dy = gMouseY - y; + + PxVec3 up; + up = PxVec3(0,1,0); + + const float translateSpeed = 0.1f; + + if (gCamera.translate) + { + PxVec3 &pos = gCamera.trackballMode ? gCamera.trackballCenter : gCamera.pos; + pos += gCamera.right * dx * translateSpeed; + pos -= up * dy * translateSpeed; + } + else if (gCamera.rotate) + { + const float rotationSpeed = 0.01f; + if (gCamera.trackballMode) { + gCamera.forward.normalize(); + gCamera.right = gCamera.forward.cross(PxVec3(0,1,0)); + + PxQuat qy(dx * rotationSpeed, PxVec3(0.0f, 1.0f, 0.0f)); + gCamera.forward = qy.rotate(gCamera.forward); + PxQuat qx(dy * rotationSpeed, gCamera.right); + gCamera.forward = qx.rotate(gCamera.forward); + gCamera.forward.y = PxClamp(gCamera.forward.y, 0.9f, -0.9f); + gCamera.forward.normalize(); + gCamera.pos = gCamera.trackballCenter - gCamera.forward * gCamera.trackballRadius; + } + else { + PxQuat qx(dx * rotationSpeed, up); + gCamera.forward = qx.rotate(gCamera.forward); + PxQuat qy(dy * rotationSpeed, gCamera.right); + PxVec3 tempForward = gCamera.forward; + gCamera.forward = qy.rotate(gCamera.forward); + gCamera.forward.normalize(); + + if (PxAbs(gCamera.forward.y) > 0.98f) + { + //Clamp the axis... + gCamera.forward = tempForward; + gCamera.forward.normalize(); + } + } + } + else if (gCamera.zoom) { + if (gCamera.trackballMode) + gCamera.trackballRadius *= 1.0f + 0.01f * dy; + else + gCamera.pos -= gCamera.forward * dy * translateSpeed; + } + + gMouseX = x; + gMouseY = y; + + if (gSampleScene != NULL) + gSampleScene->handleMouseMotion(x, y); +} + +// ------------------------------------------------------------------------------------ + +void InitGlutCallbacks(bool fullscreen, int width, int height) +{ + if (fullScreen) { + char modeS[500]; + sprintf(modeS, "%dx%d:32@60", width, height); + glutGameModeString(modeS); + glutEnterGameMode(); + } + else { + gMainHandle = glutCreateWindow("Sample Viewer"); + glutSetWindow(gMainHandle); + } + glutDisplayFunc(RenderCallback); + glutReshapeFunc(ReshapeCallback); + glutIdleFunc(IdleCallback); + glutKeyboardFunc(KeyboardCallback); + glutKeyboardUpFunc(KeyboardUpCallback); + glutSpecialFunc(SpecialCallback); + glutMouseFunc(MouseCallback); + glutMotionFunc(MotionCallback); + glutPassiveMotionFunc(MotionCallback); + MotionCallback(0, 0); +} + +void InitGlut(int argc, char **argv) +{ + //printf("glutInit\n"); + + glutInit(&argc, argv); + glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); + + InitGlutCallbacks(fullScreen, WINDOW_WIDTH, WINDOW_HEIGHT); + + sampleViewerGamepad.init(); + + // Setup default render states + glEnable(GL_DEPTH_TEST); + glEnable(GL_COLOR_MATERIAL); + //glEnable(GL_CULL_FACE); + glShadeModel(GL_SMOOTH); +#ifdef WIN32 + glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); + glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); +#endif + + // Setup lighting + glEnable(GL_LIGHTING); +// float AmbientColor[] = { 0.0f, 0.1f, 0.2f, 0.0f }; glLightfv(GL_LIGHT0, GL_AMBIENT, AmbientColor); +// float DiffuseColor[] = { 0.8f, 0.8f, 0.8f, 0.0f }; glLightfv(GL_LIGHT0, GL_DIFFUSE, DiffuseColor); +// float SpecularColor[] = { 0.7f, 0.7f, 0.7f, 0.0f }; glLightfv(GL_LIGHT0, GL_SPECULAR, SpecularColor); + + float AmbientColor[] = { 0.0f, 0.0f, 0.0f, 0.0f }; glLightfv(GL_LIGHT0, GL_AMBIENT, AmbientColor); + float DiffuseColor[] = { 0.6f, 0.6f, 0.6f, 0.0f }; glLightfv(GL_LIGHT0, GL_DIFFUSE, DiffuseColor); + float SpecularColor[] = { 0.7f, 0.7f, 0.7f, 0.0f }; glLightfv(GL_LIGHT0, GL_SPECULAR, SpecularColor); + + + // float Position[] = { 100.0f, 100.0f, -400.0f, 1.0f }; glLightfv(GL_LIGHT0, GL_POSITION, Position); + //float Position[] = { 10.0f, 200.0f, 15.0f, 0.0f }; glLightfv(GL_LIGHT0, GL_POSITION, Position); + + //float Position[] = { -400,200,300, 0.0f }; glLightfv(GL_LIGHT0, GL_POSITION, Position); +#if !TEST_ART_GALLERY_FLOOR + float Position[] = { -400,200,300, 0.0f }; glLightfv(GL_LIGHT0, GL_POSITION, Position); +#else + float Position[] = { 674,-300,200, 0.0f }; glLightfv(GL_LIGHT0, GL_POSITION, Position); +#endif + glEnable(GL_LIGHT0); + glEnable(GL_NORMALIZE); // so that lighting on scaled objects is correct + + + PxVec3 target = PxVec3(0.0f, 8.0f, -25.0f); + gCamera.forward = target - gCamera.pos; + gCamera.forward.normalize(); + + for (int i = 0; i < gNumLights; i++) + gShadowMaps[i] = NULL; + + GLenum err = glewInit(); + if (err != GLEW_OK) { + printf("glewInit() failed\n"); + exit(0); + } + + // Setup Fog + glEnable (GL_FOG); + float fogColor[4] = {180.0f/255.0f,182.0f/255.0f,202.0f/255.0f,1.0f}; + glFogi (GL_FOG_MODE, GL_LINEAR); + + glFogf(GL_FOG_DENSITY, 0.0009f); + glFogf(GL_FOG_START, g_fogStart); + glFogf(GL_FOG_END, g_fogEnd); + glFogfv (GL_FOG_COLOR, fogColor); + + // Load ground texture + gSplashScreenTexId = 0; + + gDisplayTexArrayProg = new Shader(); + gDisplayTexArrayProg->loadShaderCode(passThruVS, texture2DArrayPS); + + gDisplaySplashProg = new Shader(); + gDisplaySplashProg->loadShaderCode(passThruVS, textureRECTPS); + + if (doAA) { + g_pAABox = new AABox(gResourcePath); + g_pAABox->Initialize(WINDOW_WIDTH, WINDOW_HEIGHT, g_curSSSize, g_aaModes[g_curAA].ds, g_aaModes[g_curAA].cs); + } + + if (gDoHDR) + { + ShaderShadow::hdrScale = 2.0f; + } + + gDefaultShader = new ShaderShadow(ShaderShadow::VS_DEFAULT, ShaderShadow::PS_SHADE); + gDefaultShader->init(); + + /* + TCHAR pwd[500]; + GetCurrentDirectory(500,pwd); + MessageBox(NULL,pwd,pwd,0); +*/ + gFXAAHelper = new FXAAHelper(gResourcePath); + gSSAOHelper = new SSAOHelper(gCamera.fov, 0.1f, zNear, zFar, gResourcePath, doAA ? (1.0f/g_curSSSize) : 1.0f); + gHBAOHelper = new HBAOHelper(gCamera.fov, zNear, zFar); + gHDRHelper = new HDRHelper(gCamera.fov, 0.1f, zNear, zFar, gResourcePath, doAA ? (1.0f/g_curSSSize) : 1.0f); + + gDisplayTexArrayProg->loadShaders((string(gResourcePath) + string("\\shaders\\passthrough_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\shadowdebug_fs.cpp")).c_str()); + gDefaultShader->loadShaders((string(gResourcePath) + string("\\shaders\\default_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\default_fs.cpp")).c_str()); + gHDRHelper->mShaderDOF.loadShaders((string(gResourcePath) + string("\\shaders\\dof_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\dof_fs.cpp")).c_str()); + gHDRHelper->mShaderBloomH.loadShaders((string(gResourcePath) + string("\\shaders\\dof_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\bloomH_fs.cpp")).c_str()); + gHDRHelper->mShaderBloomV.loadShaders((string(gResourcePath) + string("\\shaders\\dof_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\bloomV_fs.cpp")).c_str()); + gSSAOHelper->SSAOFilterH.loadShaders((string(gResourcePath) + string("\\shaders\\filterv_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\filterh_fs.cpp")).c_str()); + gSSAOHelper->SSAOFilterV.loadShaders((string(gResourcePath) + string("\\shaders\\filterv_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\filterv_fs.cpp")).c_str()); + gForceReloadDebugShader = false; + + + if (gSceneNr == 7) { + gCamera.pos = PxVec3(0.0319193f,3.24621f, 3.47924f); + } +} + +extern int numCylinderSeg ; +// ------------------------------------------------------------------------------------ +static bool parse_value_arg( std::string const& arg, std::string const& name, int& value ) +{ + if (arg.substr(0, name.length() + 1) == (name + "=")) { + value = atoi( arg.substr(name.length() + 1).c_str()); + return true; + } + return false; +} + +static bool starts_with( std::string const& arg, std::string const& text ) +{ + return arg.find( text ) == 0; +} + +#define SQR(x) ((x)*(x)) // x^2 + +// Constants +#define M_SQRT3 1.73205080756887729352744634151 // sqrt(3) + // x^2 + + +// ---------------------------------------------------------------------------- +int dsyevc3(float A[3][3], float w[3]) +// ---------------------------------------------------------------------------- +// Calculates the eigenvalues of a symmetric 3x3 matrix A using Cardano's +// analytical algorithm. +// Only the diagonal and upper triangular parts of A are accessed. The access +// is read-only. +// ---------------------------------------------------------------------------- +// Parameters: +// A: The symmetric input matrix +// w: Storage buffer for eigenvalues +// ---------------------------------------------------------------------------- +// Return value: +// 0: Success +// -1: Error +// ---------------------------------------------------------------------------- +{ + float m, c1, c0; + + // Determine coefficients of characteristic poynomial. We write + // | a d f | + // A = | d* b e | + // | f* e* c | + float de = A[0][1] * A[1][2]; // d * e + float dd = SQR(A[0][1]); // d^2 + float ee = SQR(A[1][2]); // e^2 + float ff = SQR(A[0][2]); // f^2 + m = A[0][0] + A[1][1] + A[2][2]; + c1 = (A[0][0]*A[1][1] + A[0][0]*A[2][2] + A[1][1]*A[2][2]) // a*b + a*c + b*c - d^2 - e^2 - f^2 + - (dd + ee + ff); + c0 = A[2][2]*dd + A[0][0]*ee + A[1][1]*ff - A[0][0]*A[1][1]*A[2][2] + - 2.0 * A[0][2]*de; // c*d^2 + a*e^2 + b*f^2 - a*b*c - 2*f*d*e) + + float p, sqrt_p, q, c, s, phi; + p = SQR(m) - 3.0*c1; + q = m*(p - (3.0/2.0)*c1) - (27.0/2.0)*c0; + sqrt_p = sqrtf(fabs(p)); + + phi = 27.0 * ( 0.25*SQR(c1)*(p - c1) + c0*(q + 27.0/4.0*c0)); + phi = (1.0/3.0) * atan2(sqrt(fabs(phi)), q); + + c = sqrt_p*cosf(phi); + s = (1.0/M_SQRT3)*sqrt_p*sinf(phi); + + w[1] = (1.0/3.0)*(m - c); + w[2] = w[1] + s; + w[0] = w[1] + c; + w[1] -= s; + + return 0; +} + +// ---------------------------------------------------------------------------- +int dsyevv3(float A[3][3], float Q[3][3], float w[3]) +// ---------------------------------------------------------------------------- +// Calculates the eigenvalues and normalized eigenvectors of a symmetric 3x3 +// matrix A using Cardano's method for the eigenvalues and an analytical +// method based on vector cross products for the eigenvectors. +// Only the diagonal and upper triangular parts of A need to contain meaningful +// values. However, all of A may be used as temporary storage and may hence be +// destroyed. +// ---------------------------------------------------------------------------- +// Parameters: +// A: The symmetric input matrix +// Q: Storage buffer for eigenvectors +// w: Storage buffer for eigenvalues +// ---------------------------------------------------------------------------- +// Return value: +// 0: Success +// -1: Error +// ---------------------------------------------------------------------------- +// Dependencies: +// dsyevc3() +// ---------------------------------------------------------------------------- +// Version history: +// v1.1 (12 Mar 2012): Removed access to lower triangualr part of A +// (according to the documentation, only the upper triangular part needs +// to be filled) +// v1.0: First released version +// ---------------------------------------------------------------------------- +{ +#ifndef EVALS_ONLY + float norm; // Squared norm or inverse norm of current eigenvector + float n0, n1; // Norm of first and second columns of A + float n0tmp, n1tmp; // "Templates" for the calculation of n0/n1 - saves a few FLOPS + float thresh; // Small number used as threshold for floating point comparisons + float error; // Estimated maximum roundoff error in some steps + float wmax; // The eigenvalue of maximum modulus + float f, t; // Intermediate storage + int i, j; // Loop counters +#endif + + // Calculate eigenvalues + dsyevc3(A, w); + +#ifndef EVALS_ONLY + wmax = fabs(w[0]); + if ((t=fabs(w[1])) > wmax) + wmax = t; + if ((t=fabs(w[2])) > wmax) + wmax = t; + thresh = SQR(8.0 * DBL_EPSILON * wmax); + + // Prepare calculation of eigenvectors + n0tmp = SQR(A[0][1]) + SQR(A[0][2]); + n1tmp = SQR(A[0][1]) + SQR(A[1][2]); + Q[0][1] = A[0][1]*A[1][2] - A[0][2]*A[1][1]; + Q[1][1] = A[0][2]*A[0][1] - A[1][2]*A[0][0]; + Q[2][1] = SQR(A[0][1]); + + // Calculate first eigenvector by the formula + // v[0] = (A - w[0]).e1 x (A - w[0]).e2 + A[0][0] -= w[0]; + A[1][1] -= w[0]; + Q[0][0] = Q[0][1] + A[0][2]*w[0]; + Q[1][0] = Q[1][1] + A[1][2]*w[0]; + Q[2][0] = A[0][0]*A[1][1] - Q[2][1]; + norm = SQR(Q[0][0]) + SQR(Q[1][0]) + SQR(Q[2][0]); + n0 = n0tmp + SQR(A[0][0]); + n1 = n1tmp + SQR(A[1][1]); + error = n0 * n1; + + if (n0 <= thresh) // If the first column is zero, then (1,0,0) is an eigenvector + { + Q[0][0] = 1.0; + Q[1][0] = 0.0; + Q[2][0] = 0.0; + } + else if (n1 <= thresh) // If the second column is zero, then (0,1,0) is an eigenvector + { + Q[0][0] = 0.0; + Q[1][0] = 1.0; + Q[2][0] = 0.0; + } + else if (norm < SQR(64.0 * DBL_EPSILON) * error) + { // If angle between A[0] and A[1] is too small, don't use + t = SQR(A[0][1]); // cross product, but calculate v ~ (1, -A0/A1, 0) + f = -A[0][0] / A[0][1]; + if (SQR(A[1][1]) > t) + { + t = SQR(A[1][1]); + f = -A[0][1] / A[1][1]; + } + if (SQR(A[1][2]) > t) + f = -A[0][2] / A[1][2]; + norm = 1.0/sqrt(1 + SQR(f)); + Q[0][0] = norm; + Q[1][0] = f * norm; + Q[2][0] = 0.0; + } + else // This is the standard branch + { + norm = sqrt(1.0 / norm); + for (j=0; j < 3; j++) + Q[j][0] = Q[j][0] * norm; + } + + + // Prepare calculation of second eigenvector + t = w[0] - w[1]; + if (fabs(t) > 8.0 * DBL_EPSILON * wmax) + { + // For non-degenerate eigenvalue, calculate second eigenvector by the formula + // v[1] = (A - w[1]).e1 x (A - w[1]).e2 + A[0][0] += t; + A[1][1] += t; + Q[0][1] = Q[0][1] + A[0][2]*w[1]; + Q[1][1] = Q[1][1] + A[1][2]*w[1]; + Q[2][1] = A[0][0]*A[1][1] - Q[2][1]; + norm = SQR(Q[0][1]) + SQR(Q[1][1]) + SQR(Q[2][1]); + n0 = n0tmp + SQR(A[0][0]); + n1 = n1tmp + SQR(A[1][1]); + error = n0 * n1; + + if (n0 <= thresh) // If the first column is zero, then (1,0,0) is an eigenvector + { + Q[0][1] = 1.0; + Q[1][1] = 0.0; + Q[2][1] = 0.0; + } + else if (n1 <= thresh) // If the second column is zero, then (0,1,0) is an eigenvector + { + Q[0][1] = 0.0; + Q[1][1] = 1.0; + Q[2][1] = 0.0; + } + else if (norm < SQR(64.0 * DBL_EPSILON) * error) + { // If angle between A[0] and A[1] is too small, don't use + t = SQR(A[0][1]); // cross product, but calculate v ~ (1, -A0/A1, 0) + f = -A[0][0] / A[0][1]; + if (SQR(A[1][1]) > t) + { + t = SQR(A[1][1]); + f = -A[0][1] / A[1][1]; + } + if (SQR(A[1][2]) > t) + f = -A[0][2] / A[1][2]; + norm = 1.0/sqrt(1 + SQR(f)); + Q[0][1] = norm; + Q[1][1] = f * norm; + Q[2][1] = 0.0; + } + else + { + norm = sqrt(1.0 / norm); + for (j=0; j < 3; j++) + Q[j][1] = Q[j][1] * norm; + } + } + else + { + // For degenerate eigenvalue, calculate second eigenvector according to + // v[1] = v[0] x (A - w[1]).e[i] + // + // This would really get to complicated if we could not assume all of A to + // contain meaningful values. + A[1][0] = A[0][1]; + A[2][0] = A[0][2]; + A[2][1] = A[1][2]; + A[0][0] += w[0]; + A[1][1] += w[0]; + for (i=0; i < 3; i++) + { + A[i][i] -= w[1]; + n0 = SQR(A[0][i]) + SQR(A[1][i]) + SQR(A[2][i]); + if (n0 > thresh) + { + Q[0][1] = Q[1][0]*A[2][i] - Q[2][0]*A[1][i]; + Q[1][1] = Q[2][0]*A[0][i] - Q[0][0]*A[2][i]; + Q[2][1] = Q[0][0]*A[1][i] - Q[1][0]*A[0][i]; + norm = SQR(Q[0][1]) + SQR(Q[1][1]) + SQR(Q[2][1]); + if (norm > SQR(256.0 * DBL_EPSILON) * n0) // Accept cross product only if the angle between + { // the two vectors was not too small + norm = sqrt(1.0 / norm); + for (j=0; j < 3; j++) + Q[j][1] = Q[j][1] * norm; + break; + } + } + } + + if (i == 3) // This means that any vector orthogonal to v[0] is an EV. + { + for (j=0; j < 3; j++) + if (Q[j][0] != 0.0) // Find nonzero element of v[0] ... + { // ... and swap it with the next one + norm = 1.0 / sqrt(SQR(Q[j][0]) + SQR(Q[(j+1)%3][0])); + Q[j][1] = Q[(j+1)%3][0] * norm; + Q[(j+1)%3][1] = -Q[j][0] * norm; + Q[(j+2)%3][1] = 0.0; + break; + } + } + } + + + // Calculate third eigenvector according to + // v[2] = v[0] x v[1] + Q[0][2] = Q[1][0]*Q[2][1] - Q[2][0]*Q[1][1]; + Q[1][2] = Q[2][0]*Q[0][1] - Q[0][0]*Q[2][1]; + Q[2][2] = Q[0][0]*Q[1][1] - Q[1][0]*Q[0][1]; +#endif + + return 0; +} + +int main(int argc, char** argv) +{ + /* + float A[3][3] = {{-4,2,1}, + {2,9,-3}, + {1,-3,-7}}; + float Q[3][3]; + float w[3]; + + dsyevv3(A,Q,w); + printf("%f %f %f\n", w[0], w[1], w[2]); + + return 0; + */ + strcpy(gResourcePath, "../../../externalIP/resources"); + gCamera.init(); + + FILE *f = fopen("resourcePath.txt", "r"); + if (f != NULL) { + fgets(gResourcePath, 512, f); + fclose(f); + } + + const char* usage = "Usage:\n" + " -msaa Do MSAA Antialiasing (Slower, but better quality). On by default. \n" + " -fxaa Do FXAA Antialiasing (Faster, but poorer quality)\n" + " -nbThreads n Use n worker threads in PhysX\n" + " -nossao Disable SSAO\n" + " -nhdr Disable HDR\n" + " -grb Use GRB (default is on)\n" + " -nogrb Use software PhysX\n" + " -maxSubSteps n Enable up to n sub-steps per-frame." + "\n" + ; + printf(usage); + + std::string render_opts; + for (int i = 1; i < argc; i++) { + std::string arg = argv[i]; + std::transform(&arg[0], &arg[0] + arg.length(), &arg[0], tolower); + if (arg == "-nogrb") { gUseGrb = false; gCurrentUsingGrb = false; } + else if (arg == "-grb") gUseGrb = true; + else if (arg == "-msaa") { + doAA = true; + doFXAA = false; + } + else if (arg == "-fxaa") { + doFXAA = true; + doAA = false; + } + else if (arg == "-maxsubsteps") + { + if (argc > (1 + i)) + { + PxU32 substepCount = atoi(argv[i + 1]); + gMaxSubSteps = substepCount; + i++; + } + } + else if (arg == "-nbthreads") + { + if (argc > (1 + i)) + { + PxU32 nbThreads = atoi(argv[i + 1]); + gNrWorkerThreads = nbThreads; + i++; + } + } + else if (arg == "-nossao") + { + gDoSSAO = false; + } + else if (arg == "-nohdr") + { + gDoHDR = false; + } + + } + + if (!InitPhysX()) { + ReleaseSDKs(); + return 0; + } + + InitGlut(argc, argv); + + if (!render_opts.empty()) { + SampleViewerScene::setRendererOptions(render_opts.c_str()); + } + + // Initialize physics scene and start the application main loop if scene was created + + SampleViewerScene::setRenderType(SampleViewerScene::rtOPENGL); + + gFontRenderer = new GLFontRenderer(); + + CreateSampleViewerScene(); + + //Hack! When rendering the first frame of the demo, various extremely large graphics buffers are allocated. In GPUs with relatively small amount of memory, + //these allocations can fail. This seems to relate to CUDA allocations fragmenting the heap. Therefore, we initialize the first frame to use CPU simulation, scheduling a transition to + //GPU to ensure that these large allocations succeed. They'll never be reallocated again. + //Ideally, these allocations would just happen before the GRB scene was initialized but that would require some surgery to the sample framework. + //bool useGrb = gUseGrb; + //gUseGrb = false; + RecreateSDKScenes(); + //gUseGrb = useGrb; + + //gForceSceneRecreate = useGrb; + + InitSampleViewerScene(); + + atexit(CleanupSample); + + glutMainLoop(); +} -- cgit v1.2.3