Files
PhysX4.1/kaplademo/source/kaplaDemo/SampleViewer.cpp
2025-11-28 23:13:44 +05:30

2259 lines
60 KiB
C++

//
// 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 <windows.h>
#endif
#undef random
#include <stdio.h>
#include <assert.h>
#include "ShaderShadow.h"
#include "ShadowMap.h"
#include "RenderTarget.h"
#include <GL/glut.h>
#include "SampleViewer.h"
#include "MediaPath.h"
#include <task/PxTask.h>
#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 <string>
#include <algorithm>
//#include "fomHelper.h"
#include <string>
#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<Compound*> 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 <direct.h>
// ------------------------------------------------------------------------------------
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<PxActor*> 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;i<len;i++)
{
if(gDisplayString[i] == '\n' || i == len-1)
{
int offset = i;
if(i == len-1) offset= i+1;
memcpy(textBuffer, gDisplayString+start, offset-start);
textBuffer[offset-start]=0;
gFontRenderer->print(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();
}