// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // * Neither the name of NVIDIA CORPORATION nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Copyright (c) 2011-2018 NVIDIA Corporation. All rights reserved. #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/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 "HDRHelper.h" #include "SampleViewerGamepad.h" #include "PhysXMacros.h" #include "pvd/PxPvdTransport.h" #include "foundation/PxMat44.h" #include "PsTime.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 gUseVSync = false; PxU32 gMinSimulatedFrames = 0; 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] = "../../../externals/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; if (strcmp(&path[len-4], ".jpg") == 0) { printf("Error loading %s, jpg no longer supported\n", path); return false; } 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.cudaContextManager = gCudaContextManager; 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.sceneQueryUpdateMode = PxSceneQueryUpdateMode::eBUILD_ENABLED_COMMIT_DISABLED; sceneDesc.gpuDynamicsConfig.constraintBufferCapacity *= 2; sceneDesc.gpuDynamicsConfig.contactBufferCapacity *= 2; //!< Capacity of contact buffer allocated in GPU global memory sceneDesc.gpuDynamicsConfig.tempBufferCapacity *= 2; //!< Capacity of temp buffer allocated in pinned host memory. sceneDesc.gpuDynamicsConfig.contactStreamSize *= 2; //!< Size of contact stream buffer allocated in pinned host memory. This is double-buffered so total allocation size = 2* contactStreamCapacity * sizeof(PxContact). sceneDesc.gpuDynamicsConfig.patchStreamSize *= 2; //!< Size of the contact patch stream buffer allocated in pinned host memory. This is double-buffered so total allocation size = 2 * patchStreamCapacity * sizeof(PxContactPatch). sceneDesc.gpuDynamicsConfig.forceStreamCapacity *= 2; //!< Capacity of force buffer allocated in pinned host memory. 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_PHYSICS_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; } // ------------------------------------------------------------------------------------ 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(); static uint64_t prevTime = physx::shdfnd::Time::getCurrentTimeInTensOfNanoSeconds(); uint64_t currTime = physx::shdfnd::Time::getCurrentTimeInTensOfNanoSeconds(); uint64_t elapsedTime = currTime - prevTime; uint64_t timestepSize = uint64_t(gTimeStepSize * 1e8f); PxReal fSubsteps = elapsedTime / timestepSize; PxU32 iSubsteps = PxMax(gMinSimulatedFrames, PxU32(fSubsteps)); PxU32 nbSubsteps = PxMin(iSubsteps, gMaxSubSteps); if (elapsedTime > timestepSize) { prevTime += timestepSize*iSubsteps; } for (PxU32 a = 0; a < nbSubsteps; ++a) { 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((a + 1) < nbSubsteps) { WaitForSim(); if (gSampleScene != NULL) { gSampleScene->postSim(gTimeStepSize); } } } } } // ------------------------------------------------------------------------------------ void EndSimulation(void) { if(g_simulationRunning == true) { PxReal dt = g_simulationDT; if (gSceneRunning) { //fetchResult WaitForSim(); if (gSampleScene != NULL) { gSampleScene->postSim(gTimeStepSize); } } ++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, " F3: Uncap simulation rate\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; 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); } if (!gPause) EndSimulation(); glutSwapBuffers(); glutReportErrors(); 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, "Kapla 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; break; } case GLUT_KEY_F3: { gMinSimulatedFrames = 1 - gMinSimulatedFrames; break; } } 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 SetVSync(bool sync) { typedef BOOL(APIENTRY *PFNWGLSWAPINTERVALPROC)(int); PFNWGLSWAPINTERVALPROC wglSwapIntervalEXT = 0; const char *extensions = (char*)glGetString(GL_EXTENSIONS); wglSwapIntervalEXT = (PFNWGLSWAPINTERVALPROC)wglGetProcAddress("wglSwapIntervalEXT"); if (wglSwapIntervalEXT) wglSwapIntervalEXT(sync); } 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); SetVSync(gUseVSync); 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); } } int main(int argc, char** argv) { strcpy(gResourcePath, "../../../externals/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" " -vsync Enables vsync (off by default)\n" "\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; } else if (arg == "-vsync") { gUseVSync = true; } } 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(); }