| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #include "../core/types.h" |
| #include "../core/maths.h" |
| #include "../core/platform.h" |
| #include "../core/mesh.h" |
| #include "../core/voxelize.h" |
| #include "../core/sdf.h" |
| #include "../core/pfm.h" |
| #include "../core/tga.h" |
| #include "../core/perlin.h" |
| #include "../core/convex.h" |
| #include "../core/cloth.h" |
|
|
| #include "../external/SDL2-2.0.4/include/SDL.h" |
|
|
| #include "../include/NvFlex.h" |
| #include "../include/NvFlexExt.h" |
| #include "../include/NvFlexDevice.h" |
|
|
| #include <iostream> |
| #include <map> |
|
|
| #include "shaders.h" |
| #include "imgui.h" |
|
|
| #include "shadersDemoContext.h" |
|
|
| #if FLEX_DX |
| #include "d3d\appGraphCtx.h" |
| #endif |
|
|
| #if ENABLE_AFTERMATH_SUPPORT |
| #include <external/GFSDK_Aftermath_v1.21/include/GFSDK_Aftermath.h> |
| #endif |
|
|
| SDL_Window* g_window; |
| unsigned int g_windowId; |
|
|
| #define SDL_CONTROLLER_BUTTON_LEFT_TRIGGER (SDL_CONTROLLER_BUTTON_MAX + 1) |
| #define SDL_CONTROLLER_BUTTON_RIGHT_TRIGGER (SDL_CONTROLLER_BUTTON_MAX + 2) |
|
|
| int GetKeyFromGameControllerButton(SDL_GameControllerButton button) |
| { |
| switch (button) |
| { |
| case SDL_CONTROLLER_BUTTON_DPAD_UP: { return SDLK_q; } |
| case SDL_CONTROLLER_BUTTON_DPAD_DOWN: { return SDLK_z; } |
| case SDL_CONTROLLER_BUTTON_DPAD_LEFT: { return SDLK_h; } |
| case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: { return -1; } |
| case SDL_CONTROLLER_BUTTON_START: { return SDLK_RETURN; } |
| case SDL_CONTROLLER_BUTTON_BACK: { return SDLK_ESCAPE; } |
| case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: { return SDLK_UP; } |
| case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: { return SDLK_DOWN; } |
| case SDL_CONTROLLER_BUTTON_A: { return SDLK_g; } |
| case SDL_CONTROLLER_BUTTON_B: { return SDLK_p; } |
| case SDL_CONTROLLER_BUTTON_X: { return SDLK_r; } |
| case SDL_CONTROLLER_BUTTON_Y: { return SDLK_o; } |
| case SDL_CONTROLLER_BUTTON_RIGHT_TRIGGER: { return SDLK_SPACE; } |
| default: { return -1; } |
| }; |
| }; |
|
|
| |
| |
| |
| #define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE 7849 |
| #define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689 |
| #define XINPUT_GAMEPAD_TRIGGER_THRESHOLD 30 |
|
|
| int deadzones[3] = { XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE, XINPUT_GAMEPAD_TRIGGER_THRESHOLD }; |
|
|
| inline float joyAxisFilter(int value, int stick) |
| { |
| |
| if (value < -deadzones[stick]) |
| return (value + deadzones[stick]) / (32768.0f - deadzones[stick]); |
| else if (value > deadzones[stick]) |
| return (value - deadzones[stick]) / (32768.0f - deadzones[stick]); |
| else |
| return 0.0f; |
| } |
|
|
| SDL_GameController* g_gamecontroller = NULL; |
|
|
| using namespace std; |
|
|
| int g_screenWidth = 1280; |
| int g_screenHeight = 720; |
| int g_msaaSamples = 8; |
|
|
| int g_numSubsteps; |
|
|
| |
| int g_device = -1; |
| char g_deviceName[256]; |
| bool g_vsync = true; |
|
|
| bool g_benchmark = false; |
| bool g_extensions = true; |
| bool g_teamCity = false; |
| bool g_interop = true; |
| bool g_d3d12 = false; |
| bool g_useAsyncCompute = true; |
| bool g_increaseGfxLoadForAsyncComputeTesting = false; |
| int g_graphics = 0; |
|
|
| FluidRenderer* g_fluidRenderer; |
| FluidRenderBuffers* g_fluidRenderBuffers; |
| DiffuseRenderBuffers* g_diffuseRenderBuffers; |
|
|
| NvFlexSolver* g_solver; |
| NvFlexSolverDesc g_solverDesc; |
| NvFlexLibrary* g_flexLib; |
| NvFlexParams g_params; |
| NvFlexTimers g_timers; |
| int g_numDetailTimers; |
| NvFlexDetailTimer * g_detailTimers; |
|
|
| int g_maxDiffuseParticles; |
| int g_maxNeighborsPerParticle; |
| int g_numExtraParticles; |
| int g_numExtraMultiplier = 1; |
| int g_maxContactsPerParticle; |
|
|
| |
| Mesh* g_mesh; |
| vector<int> g_meshSkinIndices; |
| vector<float> g_meshSkinWeights; |
| vector<Point3> g_meshRestPositions; |
| const int g_numSkinWeights = 4; |
|
|
| |
| std::map<NvFlexConvexMeshId, GpuMesh*> g_convexes; |
| std::map<NvFlexTriangleMeshId, GpuMesh*> g_meshes; |
| std::map<NvFlexDistanceFieldId, GpuMesh*> g_fields; |
|
|
| |
| bool g_shapesChanged = false; |
|
|
| |
| Colour g_colors[] = |
| { |
| Colour(0.0f, 0.5f, 1.0f), |
| Colour(0.797f, 0.354f, 0.000f), |
| Colour(0.092f, 0.465f, 0.820f), |
| Colour(0.000f, 0.349f, 0.173f), |
| Colour(0.875f, 0.782f, 0.051f), |
| Colour(0.000f, 0.170f, 0.453f), |
| Colour(0.673f, 0.111f, 0.000f), |
| Colour(0.612f, 0.194f, 0.394f) |
| }; |
|
|
| struct SimBuffers |
| { |
| NvFlexVector<Vec4> positions; |
| NvFlexVector<Vec4> restPositions; |
| NvFlexVector<Vec3> velocities; |
| NvFlexVector<int> phases; |
| NvFlexVector<float> densities; |
| NvFlexVector<Vec4> anisotropy1; |
| NvFlexVector<Vec4> anisotropy2; |
| NvFlexVector<Vec4> anisotropy3; |
| NvFlexVector<Vec4> normals; |
| NvFlexVector<Vec4> smoothPositions; |
| NvFlexVector<Vec4> diffusePositions; |
| NvFlexVector<Vec4> diffuseVelocities; |
| NvFlexVector<int> diffuseCount; |
|
|
| NvFlexVector<int> activeIndices; |
|
|
| |
| NvFlexVector<NvFlexCollisionGeometry> shapeGeometry; |
| NvFlexVector<Vec4> shapePositions; |
| NvFlexVector<Quat> shapeRotations; |
| NvFlexVector<Vec4> shapePrevPositions; |
| NvFlexVector<Quat> shapePrevRotations; |
| NvFlexVector<int> shapeFlags; |
|
|
| |
| NvFlexVector<int> rigidOffsets; |
| NvFlexVector<int> rigidIndices; |
| NvFlexVector<int> rigidMeshSize; |
| NvFlexVector<float> rigidCoefficients; |
| NvFlexVector<float> rigidPlasticThresholds; |
| NvFlexVector<float> rigidPlasticCreeps; |
| NvFlexVector<Quat> rigidRotations; |
| NvFlexVector<Vec3> rigidTranslations; |
| NvFlexVector<Vec3> rigidLocalPositions; |
| NvFlexVector<Vec4> rigidLocalNormals; |
|
|
| |
| NvFlexVector<int> inflatableTriOffsets; |
| NvFlexVector<int> inflatableTriCounts; |
| NvFlexVector<float> inflatableVolumes; |
| NvFlexVector<float> inflatableCoefficients; |
| NvFlexVector<float> inflatablePressures; |
|
|
| |
| NvFlexVector<int> springIndices; |
| NvFlexVector<float> springLengths; |
| NvFlexVector<float> springStiffness; |
|
|
| NvFlexVector<int> triangles; |
| NvFlexVector<Vec3> triangleNormals; |
| NvFlexVector<Vec3> uvs; |
|
|
| SimBuffers(NvFlexLibrary* l) : |
| positions(l), restPositions(l), velocities(l), phases(l), densities(l), |
| anisotropy1(l), anisotropy2(l), anisotropy3(l), normals(l), smoothPositions(l), |
| diffusePositions(l), diffuseVelocities(l), diffuseCount(l), activeIndices(l), |
| shapeGeometry(l), shapePositions(l), shapeRotations(l), shapePrevPositions(l), |
| shapePrevRotations(l), shapeFlags(l), rigidOffsets(l), rigidIndices(l), rigidMeshSize(l), |
| rigidCoefficients(l), rigidPlasticThresholds(l), rigidPlasticCreeps(l), rigidRotations(l), rigidTranslations(l), |
| rigidLocalPositions(l), rigidLocalNormals(l), inflatableTriOffsets(l), |
| inflatableTriCounts(l), inflatableVolumes(l), inflatableCoefficients(l), |
| inflatablePressures(l), springIndices(l), springLengths(l), |
| springStiffness(l), triangles(l), triangleNormals(l), uvs(l) |
| {} |
| }; |
|
|
| SimBuffers* g_buffers; |
|
|
| void MapBuffers(SimBuffers* buffers) |
| { |
| buffers->positions.map(); |
| buffers->restPositions.map(); |
| buffers->velocities.map(); |
| buffers->phases.map(); |
| buffers->densities.map(); |
| buffers->anisotropy1.map(); |
| buffers->anisotropy2.map(); |
| buffers->anisotropy3.map(); |
| buffers->normals.map(); |
| buffers->diffusePositions.map(); |
| buffers->diffuseVelocities.map(); |
| buffers->diffuseCount.map(); |
| buffers->smoothPositions.map(); |
| buffers->activeIndices.map(); |
|
|
| |
| buffers->shapeGeometry.map(); |
| buffers->shapePositions.map(); |
| buffers->shapeRotations.map(); |
| buffers->shapePrevPositions.map(); |
| buffers->shapePrevRotations.map(); |
| buffers->shapeFlags.map(); |
|
|
| buffers->rigidOffsets.map(); |
| buffers->rigidIndices.map(); |
| buffers->rigidMeshSize.map(); |
| buffers->rigidCoefficients.map(); |
| buffers->rigidPlasticThresholds.map(); |
| buffers->rigidPlasticCreeps.map(); |
| buffers->rigidRotations.map(); |
| buffers->rigidTranslations.map(); |
| buffers->rigidLocalPositions.map(); |
| buffers->rigidLocalNormals.map(); |
|
|
| buffers->springIndices.map(); |
| buffers->springLengths.map(); |
| buffers->springStiffness.map(); |
|
|
| |
| buffers->inflatableTriOffsets.map(); |
| buffers->inflatableTriCounts.map(); |
| buffers->inflatableVolumes.map(); |
| buffers->inflatableCoefficients.map(); |
| buffers->inflatablePressures.map(); |
|
|
| buffers->triangles.map(); |
| buffers->triangleNormals.map(); |
| buffers->uvs.map(); |
| } |
|
|
| void UnmapBuffers(SimBuffers* buffers) |
| { |
| |
| buffers->positions.unmap(); |
| buffers->restPositions.unmap(); |
| buffers->velocities.unmap(); |
| buffers->phases.unmap(); |
| buffers->densities.unmap(); |
| buffers->anisotropy1.unmap(); |
| buffers->anisotropy2.unmap(); |
| buffers->anisotropy3.unmap(); |
| buffers->normals.unmap(); |
| buffers->diffusePositions.unmap(); |
| buffers->diffuseVelocities.unmap(); |
| buffers->diffuseCount.unmap(); |
| buffers->smoothPositions.unmap(); |
| buffers->activeIndices.unmap(); |
|
|
| |
| buffers->shapeGeometry.unmap(); |
| buffers->shapePositions.unmap(); |
| buffers->shapeRotations.unmap(); |
| buffers->shapePrevPositions.unmap(); |
| buffers->shapePrevRotations.unmap(); |
| buffers->shapeFlags.unmap(); |
|
|
| |
| buffers->rigidOffsets.unmap(); |
| buffers->rigidIndices.unmap(); |
| buffers->rigidMeshSize.unmap(); |
| buffers->rigidCoefficients.unmap(); |
| buffers->rigidPlasticThresholds.unmap(); |
| buffers->rigidPlasticCreeps.unmap(); |
| buffers->rigidRotations.unmap(); |
| buffers->rigidTranslations.unmap(); |
| buffers->rigidLocalPositions.unmap(); |
| buffers->rigidLocalNormals.unmap(); |
|
|
| |
| buffers->springIndices.unmap(); |
| buffers->springLengths.unmap(); |
| buffers->springStiffness.unmap(); |
|
|
| |
| buffers->inflatableTriOffsets.unmap(); |
| buffers->inflatableTriCounts.unmap(); |
| buffers->inflatableVolumes.unmap(); |
| buffers->inflatableCoefficients.unmap(); |
| buffers->inflatablePressures.unmap(); |
|
|
| |
| buffers->triangles.unmap(); |
| buffers->triangleNormals.unmap(); |
| buffers->uvs.unmap(); |
|
|
| } |
|
|
| SimBuffers* AllocBuffers(NvFlexLibrary* lib) |
| { |
| return new SimBuffers(lib); |
| } |
|
|
| void DestroyBuffers(SimBuffers* buffers) |
| { |
| |
| buffers->positions.destroy(); |
| buffers->restPositions.destroy(); |
| buffers->velocities.destroy(); |
| buffers->phases.destroy(); |
| buffers->densities.destroy(); |
| buffers->anisotropy1.destroy(); |
| buffers->anisotropy2.destroy(); |
| buffers->anisotropy3.destroy(); |
| buffers->normals.destroy(); |
| buffers->diffusePositions.destroy(); |
| buffers->diffuseVelocities.destroy(); |
| buffers->diffuseCount.destroy(); |
| buffers->smoothPositions.destroy(); |
| buffers->activeIndices.destroy(); |
|
|
| |
| buffers->shapeGeometry.destroy(); |
| buffers->shapePositions.destroy(); |
| buffers->shapeRotations.destroy(); |
| buffers->shapePrevPositions.destroy(); |
| buffers->shapePrevRotations.destroy(); |
| buffers->shapeFlags.destroy(); |
|
|
| |
| buffers->rigidOffsets.destroy(); |
| buffers->rigidIndices.destroy(); |
| buffers->rigidMeshSize.destroy(); |
| buffers->rigidCoefficients.destroy(); |
| buffers->rigidPlasticThresholds.destroy(); |
| buffers->rigidPlasticCreeps.destroy(); |
| buffers->rigidRotations.destroy(); |
| buffers->rigidTranslations.destroy(); |
| buffers->rigidLocalPositions.destroy(); |
| buffers->rigidLocalNormals.destroy(); |
|
|
| |
| buffers->springIndices.destroy(); |
| buffers->springLengths.destroy(); |
| buffers->springStiffness.destroy(); |
|
|
| |
| buffers->inflatableTriOffsets.destroy(); |
| buffers->inflatableTriCounts.destroy(); |
| buffers->inflatableVolumes.destroy(); |
| buffers->inflatableCoefficients.destroy(); |
| buffers->inflatablePressures.destroy(); |
|
|
| |
| buffers->triangles.destroy(); |
| buffers->triangleNormals.destroy(); |
| buffers->uvs.destroy(); |
|
|
| delete buffers; |
| } |
|
|
| Vec3 g_camPos(6.0f, 8.0f, 18.0f); |
| Vec3 g_camAngle(0.0f, -DegToRad(20.0f), 0.0f); |
| Vec3 g_camVel(0.0f); |
| Vec3 g_camSmoothVel(0.0f); |
|
|
| float g_camSpeed; |
| float g_camNear; |
| float g_camFar; |
|
|
| Vec3 g_lightPos; |
| Vec3 g_lightDir; |
| Vec3 g_lightTarget; |
|
|
| bool g_pause = false; |
| bool g_step = false; |
| bool g_capture = false; |
| bool g_showHelp = true; |
| bool g_tweakPanel = true; |
| bool g_fullscreen = false; |
| bool g_wireframe = false; |
| bool g_debug = false; |
|
|
| bool g_emit = false; |
| bool g_warmup = false; |
|
|
| float g_windTime = 0.0f; |
| float g_windFrequency = 0.1f; |
| float g_windStrength = 0.0f; |
|
|
| bool g_wavePool = false; |
| float g_waveTime = 0.0f; |
| float g_wavePlane; |
| float g_waveFrequency = 1.5f; |
| float g_waveAmplitude = 1.0f; |
| float g_waveFloorTilt = 0.0f; |
|
|
| Vec3 g_sceneLower; |
| Vec3 g_sceneUpper; |
|
|
| float g_blur; |
| float g_ior; |
| bool g_drawEllipsoids; |
| bool g_drawPoints; |
| bool g_drawMesh; |
| bool g_drawCloth; |
| float g_expandCloth; |
|
|
| bool g_drawOpaque; |
| int g_drawSprings; |
| bool g_drawBases = false; |
| bool g_drawContacts = false; |
| bool g_drawNormals = false; |
| bool g_drawDiffuse; |
| bool g_drawShapeGrid = false; |
| bool g_drawDensity = false; |
| bool g_drawRopes; |
| float g_pointScale; |
| float g_ropeScale; |
| float g_drawPlaneBias; |
|
|
| float g_diffuseScale; |
| float g_diffuseMotionScale; |
| bool g_diffuseShadow; |
| float g_diffuseInscatter; |
| float g_diffuseOutscatter; |
|
|
| float g_dt = 1.0f / 60.0f; |
| float g_realdt; |
|
|
| float g_waitTime; |
| float g_updateTime; |
| float g_renderTime; |
| |
| float g_simLatency; |
|
|
| int g_scene = 0; |
| int g_selectedScene = g_scene; |
| int g_levelScroll; |
| bool g_resetScene = false; |
|
|
| int g_frame = 0; |
| int g_numSolidParticles = 0; |
|
|
| int g_mouseParticle = -1; |
| float g_mouseT = 0.0f; |
| Vec3 g_mousePos; |
| float g_mouseMass; |
| bool g_mousePicked = false; |
|
|
| |
| int g_lastx; |
| int g_lasty; |
| int g_lastb = -1; |
|
|
| bool g_profile = false; |
| bool g_outputAllFrameTimes = false; |
| bool g_asyncComputeBenchmark = false; |
|
|
| ShadowMap* g_shadowMap; |
|
|
| Vec4 g_fluidColor; |
| Vec4 g_diffuseColor; |
| Vec3 g_meshColor; |
| Vec3 g_clearColor; |
| float g_lightDistance; |
| float g_fogDistance; |
|
|
| FILE* g_ffmpeg; |
|
|
| void DrawShapes(); |
|
|
| class Scene; |
| vector<Scene*> g_scenes; |
|
|
| struct Emitter |
| { |
| Emitter() : mSpeed(0.0f), mEnabled(false), mLeftOver(0.0f), mWidth(8) {} |
|
|
| Vec3 mPos; |
| Vec3 mDir; |
| Vec3 mRight; |
| float mSpeed; |
| bool mEnabled; |
| float mLeftOver; |
| int mWidth; |
| }; |
|
|
| vector<Emitter> g_emitters(1); |
|
|
| struct Rope |
| { |
| std::vector<int> mIndices; |
| }; |
|
|
| vector<Rope> g_ropes; |
|
|
| inline float sqr(float x) { return x*x; } |
|
|
| #include "helpers.h" |
| #include "scenes.h" |
| #include "benchmark.h" |
|
|
| void Init(int scene, bool centerCamera = true) |
| { |
| RandInit(); |
|
|
| if (g_solver) |
| { |
| if (g_buffers) |
| DestroyBuffers(g_buffers); |
|
|
| DestroyFluidRenderBuffers(g_fluidRenderBuffers); |
| DestroyDiffuseRenderBuffers(g_diffuseRenderBuffers); |
|
|
| for (auto& iter : g_meshes) |
| { |
| NvFlexDestroyTriangleMesh(g_flexLib, iter.first); |
| DestroyGpuMesh(iter.second); |
| } |
|
|
| for (auto& iter : g_fields) |
| { |
| NvFlexDestroyDistanceField(g_flexLib, iter.first); |
| DestroyGpuMesh(iter.second); |
| } |
|
|
| for (auto& iter : g_convexes) |
| { |
| NvFlexDestroyConvexMesh(g_flexLib, iter.first); |
| DestroyGpuMesh(iter.second); |
| } |
|
|
|
|
| g_fields.clear(); |
| g_meshes.clear(); |
| g_convexes.clear(); |
|
|
| NvFlexDestroySolver(g_solver); |
| g_solver = NULL; |
| } |
|
|
| |
| g_buffers = AllocBuffers(g_flexLib); |
|
|
| |
| MapBuffers(g_buffers); |
|
|
| g_buffers->positions.resize(0); |
| g_buffers->velocities.resize(0); |
| g_buffers->phases.resize(0); |
|
|
| g_buffers->rigidOffsets.resize(0); |
| g_buffers->rigidIndices.resize(0); |
| g_buffers->rigidMeshSize.resize(0); |
| g_buffers->rigidRotations.resize(0); |
| g_buffers->rigidTranslations.resize(0); |
| g_buffers->rigidCoefficients.resize(0); |
| g_buffers->rigidPlasticThresholds.resize(0); |
| g_buffers->rigidPlasticCreeps.resize(0); |
| g_buffers->rigidLocalPositions.resize(0); |
| g_buffers->rigidLocalNormals.resize(0); |
|
|
| g_buffers->springIndices.resize(0); |
| g_buffers->springLengths.resize(0); |
| g_buffers->springStiffness.resize(0); |
| g_buffers->triangles.resize(0); |
| g_buffers->triangleNormals.resize(0); |
| g_buffers->uvs.resize(0); |
|
|
| g_meshSkinIndices.resize(0); |
| g_meshSkinWeights.resize(0); |
|
|
| g_emitters.resize(1); |
| g_emitters[0].mEnabled = false; |
| g_emitters[0].mSpeed = 1.0f; |
| g_emitters[0].mLeftOver = 0.0f; |
| g_emitters[0].mWidth = 8; |
|
|
| g_buffers->shapeGeometry.resize(0); |
| g_buffers->shapePositions.resize(0); |
| g_buffers->shapeRotations.resize(0); |
| g_buffers->shapePrevPositions.resize(0); |
| g_buffers->shapePrevRotations.resize(0); |
| g_buffers->shapeFlags.resize(0); |
|
|
| g_ropes.resize(0); |
|
|
| |
| delete g_mesh; g_mesh = NULL; |
|
|
| g_frame = 0; |
| g_pause = false; |
|
|
| g_dt = 1.0f / 60.0f; |
| g_waveTime = 0.0f; |
| g_windTime = 0.0f; |
| g_windStrength = 1.0f; |
|
|
| g_blur = 1.0f; |
| g_fluidColor = Vec4(0.1f, 0.4f, 0.8f, 1.0f); |
| g_meshColor = Vec3(0.9f, 0.9f, 0.9f); |
| g_drawEllipsoids = false; |
| g_drawPoints = true; |
| g_drawCloth = true; |
| g_expandCloth = 0.0f; |
|
|
| g_drawOpaque = false; |
| g_drawSprings = false; |
| g_drawDiffuse = false; |
| g_drawMesh = true; |
| g_drawRopes = true; |
| g_drawDensity = false; |
| g_ior = 1.0f; |
| g_lightDistance = 2.0f; |
| g_fogDistance = 0.005f; |
|
|
| g_camSpeed = 0.075f; |
| g_camNear = 0.01f; |
| g_camFar = 1000.0f; |
|
|
| g_pointScale = 1.0f; |
| g_ropeScale = 1.0f; |
| g_drawPlaneBias = 0.0f; |
|
|
| |
| g_params.gravity[0] = 0.0f; |
| g_params.gravity[1] = -9.8f; |
| g_params.gravity[2] = 0.0f; |
|
|
| g_params.wind[0] = 0.0f; |
| g_params.wind[1] = 0.0f; |
| g_params.wind[2] = 0.0f; |
|
|
| g_params.radius = 0.15f; |
| g_params.viscosity = 0.0f; |
| g_params.dynamicFriction = 0.0f; |
| g_params.staticFriction = 0.0f; |
| g_params.particleFriction = 0.0f; |
| g_params.freeSurfaceDrag = 0.0f; |
| g_params.drag = 0.0f; |
| g_params.lift = 0.0f; |
| g_params.numIterations = 3; |
| g_params.fluidRestDistance = 0.0f; |
| g_params.solidRestDistance = 0.0f; |
|
|
| g_params.anisotropyScale = 1.0f; |
| g_params.anisotropyMin = 0.1f; |
| g_params.anisotropyMax = 2.0f; |
| g_params.smoothing = 1.0f; |
|
|
| g_params.dissipation = 0.0f; |
| g_params.damping = 0.0f; |
| g_params.particleCollisionMargin = 0.0f; |
| g_params.shapeCollisionMargin = 0.0f; |
| g_params.collisionDistance = 0.0f; |
| g_params.sleepThreshold = 0.0f; |
| g_params.shockPropagation = 0.0f; |
| g_params.restitution = 0.0f; |
|
|
| g_params.maxSpeed = FLT_MAX; |
| g_params.maxAcceleration = 100.0f; |
|
|
| g_params.relaxationMode = eNvFlexRelaxationLocal; |
| g_params.relaxationFactor = 1.0f; |
| g_params.solidPressure = 1.0f; |
| g_params.adhesion = 0.0f; |
| g_params.cohesion = 0.025f; |
| g_params.surfaceTension = 0.0f; |
| g_params.vorticityConfinement = 0.0f; |
| g_params.buoyancy = 1.0f; |
| g_params.diffuseThreshold = 100.0f; |
| g_params.diffuseBuoyancy = 1.0f; |
| g_params.diffuseDrag = 0.8f; |
| g_params.diffuseBallistic = 16; |
| g_params.diffuseLifetime = 2.0f; |
|
|
| g_numSubsteps = 2; |
|
|
| |
| g_params.numPlanes = 1; |
|
|
| g_diffuseScale = 0.5f; |
| g_diffuseColor = 1.0f; |
| g_diffuseMotionScale = 1.0f; |
| g_diffuseShadow = false; |
| g_diffuseInscatter = 0.8f; |
| g_diffuseOutscatter = 0.53f; |
|
|
| |
| g_colors[0] = Colour(0.0f, 0.5f, 1.0f); |
|
|
| g_numSolidParticles = 0; |
|
|
| g_waveFrequency = 1.5f; |
| g_waveAmplitude = 1.5f; |
| g_waveFloorTilt = 0.0f; |
| g_emit = false; |
| g_warmup = false; |
|
|
| g_mouseParticle = -1; |
|
|
| g_maxDiffuseParticles = 0; |
| g_maxNeighborsPerParticle = 96; |
| g_numExtraParticles = 0; |
| g_maxContactsPerParticle = 6; |
|
|
| g_sceneLower = FLT_MAX; |
| g_sceneUpper = -FLT_MAX; |
|
|
| |
| NvFlexSetSolverDescDefaults(&g_solverDesc); |
|
|
| |
| StartGpuWork(); |
| g_scenes[g_scene]->Initialize(); |
| EndGpuWork(); |
|
|
| uint32_t numParticles = g_buffers->positions.size(); |
| uint32_t maxParticles = numParticles + g_numExtraParticles*g_numExtraMultiplier; |
| |
| if (g_params.solidRestDistance == 0.0f) |
| g_params.solidRestDistance = g_params.radius; |
|
|
| |
| if (g_params.fluidRestDistance > 0.0f) |
| g_params.solidRestDistance = g_params.fluidRestDistance; |
|
|
| |
| if (g_params.collisionDistance == 0.0f) |
| g_params.collisionDistance = Max(g_params.solidRestDistance, g_params.fluidRestDistance)*0.5f; |
|
|
| |
| if (g_params.particleFriction == 0.0f) |
| g_params.particleFriction = g_params.dynamicFriction*0.1f; |
|
|
| |
| if (g_params.shapeCollisionMargin == 0.0f) |
| g_params.shapeCollisionMargin = g_params.collisionDistance*0.5f; |
|
|
| |
| Vec3 particleLower, particleUpper; |
| GetParticleBounds(particleLower, particleUpper); |
|
|
| |
| Vec3 shapeLower, shapeUpper; |
| GetShapeBounds(shapeLower, shapeUpper); |
|
|
| |
| g_sceneLower = Min(Min(g_sceneLower, particleLower), shapeLower); |
| g_sceneUpper = Max(Max(g_sceneUpper, particleUpper), shapeUpper); |
|
|
| g_sceneLower -= g_params.collisionDistance; |
| g_sceneUpper += g_params.collisionDistance; |
|
|
| |
| Vec3 up = Normalize(Vec3(-g_waveFloorTilt, 1.0f, 0.0f)); |
|
|
| (Vec4&)g_params.planes[0] = Vec4(up.x, up.y, up.z, 0.0f); |
| (Vec4&)g_params.planes[1] = Vec4(0.0f, 0.0f, 1.0f, -g_sceneLower.z); |
| (Vec4&)g_params.planes[2] = Vec4(1.0f, 0.0f, 0.0f, -g_sceneLower.x); |
| (Vec4&)g_params.planes[3] = Vec4(-1.0f, 0.0f, 0.0f, g_sceneUpper.x); |
| (Vec4&)g_params.planes[4] = Vec4(0.0f, 0.0f, -1.0f, g_sceneUpper.z); |
| (Vec4&)g_params.planes[5] = Vec4(0.0f, -1.0f, 0.0f, g_sceneUpper.y); |
|
|
| g_wavePlane = g_params.planes[2][3]; |
|
|
| g_buffers->diffusePositions.resize(g_maxDiffuseParticles); |
| g_buffers->diffuseVelocities.resize(g_maxDiffuseParticles); |
| g_buffers->diffuseCount.resize(1, 0); |
|
|
| |
| g_buffers->smoothPositions.resize(maxParticles); |
|
|
| g_buffers->normals.resize(0); |
| g_buffers->normals.resize(maxParticles); |
|
|
| |
| int numTris = g_buffers->triangles.size() / 3; |
| for (int i = 0; i < numTris; ++i) |
| { |
| Vec3 v0 = Vec3(g_buffers->positions[g_buffers->triangles[i * 3 + 0]]); |
| Vec3 v1 = Vec3(g_buffers->positions[g_buffers->triangles[i * 3 + 1]]); |
| Vec3 v2 = Vec3(g_buffers->positions[g_buffers->triangles[i * 3 + 2]]); |
|
|
| Vec3 n = Cross(v1 - v0, v2 - v0); |
|
|
| g_buffers->normals[g_buffers->triangles[i * 3 + 0]] += Vec4(n, 0.0f); |
| g_buffers->normals[g_buffers->triangles[i * 3 + 1]] += Vec4(n, 0.0f); |
| g_buffers->normals[g_buffers->triangles[i * 3 + 2]] += Vec4(n, 0.0f); |
| } |
|
|
| for (int i = 0; i < int(maxParticles); ++i) |
| g_buffers->normals[i] = Vec4(SafeNormalize(Vec3(g_buffers->normals[i]), Vec3(0.0f, 1.0f, 0.0f)), 0.0f); |
|
|
|
|
| |
| if (g_mesh) |
| { |
| g_meshRestPositions = g_mesh->m_positions; |
| } |
| else |
| { |
| g_meshRestPositions.resize(0); |
| } |
|
|
| g_solverDesc.maxParticles = maxParticles; |
| g_solverDesc.maxDiffuseParticles = g_maxDiffuseParticles; |
| g_solverDesc.maxNeighborsPerParticle = g_maxNeighborsPerParticle; |
| g_solverDesc.maxContactsPerParticle = g_maxContactsPerParticle; |
|
|
| |
| g_solver = NvFlexCreateSolver(g_flexLib, &g_solverDesc); |
|
|
| |
| g_scenes[g_scene]->PostInitialize(); |
|
|
| |
| if (centerCamera) |
| { |
| g_camPos = Vec3((g_sceneLower.x + g_sceneUpper.x)*0.5f, min(g_sceneUpper.y*1.25f, 6.0f), g_sceneUpper.z + min(g_sceneUpper.y, 6.0f)*2.0f); |
| g_camAngle = Vec3(0.0f, -DegToRad(15.0f), 0.0f); |
|
|
| |
| g_scenes[g_scene]->CenterCamera(); |
| } |
|
|
| |
| g_buffers->activeIndices.resize(g_buffers->positions.size()); |
| for (int i = 0; i < g_buffers->activeIndices.size(); ++i) |
| g_buffers->activeIndices[i] = i; |
|
|
| |
| g_buffers->positions.resize(maxParticles); |
| g_buffers->velocities.resize(maxParticles); |
| g_buffers->phases.resize(maxParticles); |
|
|
| g_buffers->densities.resize(maxParticles); |
| g_buffers->anisotropy1.resize(maxParticles); |
| g_buffers->anisotropy2.resize(maxParticles); |
| g_buffers->anisotropy3.resize(maxParticles); |
|
|
| |
| g_buffers->restPositions.resize(g_buffers->positions.size()); |
| for (int i = 0; i < g_buffers->positions.size(); ++i) |
| g_buffers->restPositions[i] = g_buffers->positions[i]; |
|
|
| |
| if (g_buffers->rigidOffsets.size()) |
| { |
| assert(g_buffers->rigidOffsets.size() > 1); |
|
|
| const int numRigids = g_buffers->rigidOffsets.size() - 1; |
|
|
| |
| |
| if (g_buffers->rigidTranslations.size() == 0) |
| { |
| g_buffers->rigidTranslations.resize(g_buffers->rigidOffsets.size() - 1, Vec3()); |
| CalculateRigidCentersOfMass(&g_buffers->positions[0], g_buffers->positions.size(), &g_buffers->rigidOffsets[0], &g_buffers->rigidTranslations[0], &g_buffers->rigidIndices[0], numRigids); |
| } |
|
|
| |
| g_buffers->rigidLocalPositions.resize(g_buffers->rigidOffsets.back()); |
| CalculateRigidLocalPositions(&g_buffers->positions[0], &g_buffers->rigidOffsets[0], &g_buffers->rigidTranslations[0], &g_buffers->rigidIndices[0], numRigids, &g_buffers->rigidLocalPositions[0]); |
|
|
| |
| g_buffers->rigidRotations.resize(g_buffers->rigidOffsets.size() - 1, Quat()); |
| } |
|
|
| |
| UnmapBuffers(g_buffers); |
|
|
| |
| |
|
|
| NvFlexCopyDesc copyDesc; |
| copyDesc.dstOffset = 0; |
| copyDesc.srcOffset = 0; |
| copyDesc.elementCount = numParticles; |
|
|
| NvFlexSetParams(g_solver, &g_params); |
| NvFlexSetParticles(g_solver, g_buffers->positions.buffer, ©Desc); |
| NvFlexSetVelocities(g_solver, g_buffers->velocities.buffer, ©Desc); |
| NvFlexSetNormals(g_solver, g_buffers->normals.buffer, ©Desc); |
| NvFlexSetPhases(g_solver, g_buffers->phases.buffer, ©Desc); |
| NvFlexSetRestParticles(g_solver, g_buffers->restPositions.buffer, ©Desc); |
|
|
| NvFlexSetActive(g_solver, g_buffers->activeIndices.buffer, ©Desc); |
| NvFlexSetActiveCount(g_solver, numParticles); |
| |
| |
| if (g_buffers->springIndices.size()) |
| { |
| assert((g_buffers->springIndices.size() & 1) == 0); |
| assert((g_buffers->springIndices.size() / 2) == g_buffers->springLengths.size()); |
|
|
| NvFlexSetSprings(g_solver, g_buffers->springIndices.buffer, g_buffers->springLengths.buffer, g_buffers->springStiffness.buffer, g_buffers->springLengths.size()); |
| } |
|
|
| |
| if (g_buffers->rigidOffsets.size()) |
| { |
| NvFlexSetRigids(g_solver, g_buffers->rigidOffsets.buffer, g_buffers->rigidIndices.buffer, g_buffers->rigidLocalPositions.buffer, g_buffers->rigidLocalNormals.buffer, g_buffers->rigidCoefficients.buffer, g_buffers->rigidPlasticThresholds.buffer, g_buffers->rigidPlasticCreeps.buffer, g_buffers->rigidRotations.buffer, g_buffers->rigidTranslations.buffer, g_buffers->rigidOffsets.size() - 1, g_buffers->rigidIndices.size()); |
| } |
|
|
| |
| if (g_buffers->inflatableTriOffsets.size()) |
| { |
| NvFlexSetInflatables(g_solver, g_buffers->inflatableTriOffsets.buffer, g_buffers->inflatableTriCounts.buffer, g_buffers->inflatableVolumes.buffer, g_buffers->inflatablePressures.buffer, g_buffers->inflatableCoefficients.buffer, g_buffers->inflatableTriOffsets.size()); |
| } |
|
|
| |
| if (g_buffers->triangles.size()) |
| { |
| NvFlexSetDynamicTriangles(g_solver, g_buffers->triangles.buffer, g_buffers->triangleNormals.buffer, g_buffers->triangles.size() / 3); |
| } |
|
|
| |
| if (g_buffers->shapeFlags.size()) |
| { |
| NvFlexSetShapes( |
| g_solver, |
| g_buffers->shapeGeometry.buffer, |
| g_buffers->shapePositions.buffer, |
| g_buffers->shapeRotations.buffer, |
| g_buffers->shapePrevPositions.buffer, |
| g_buffers->shapePrevRotations.buffer, |
| g_buffers->shapeFlags.buffer, |
| int(g_buffers->shapeFlags.size())); |
| } |
|
|
| |
| g_fluidRenderBuffers = CreateFluidRenderBuffers(maxParticles, g_interop); |
| g_diffuseRenderBuffers = CreateDiffuseRenderBuffers(g_maxDiffuseParticles, g_interop); |
|
|
| |
| if (g_warmup) |
| { |
| printf("Warming up sim..\n"); |
|
|
| |
| NvFlexParams copy = g_params; |
| copy.numIterations = 4; |
|
|
| NvFlexSetParams(g_solver, ©); |
|
|
| const int kWarmupIterations = 100; |
|
|
| for (int i = 0; i < kWarmupIterations; ++i) |
| { |
| NvFlexUpdateSolver(g_solver, 0.0001f, 1, false); |
| NvFlexSetVelocities(g_solver, g_buffers->velocities.buffer, NULL); |
| } |
|
|
| |
| NvFlexGetParticles(g_solver, g_buffers->positions.buffer, NULL); |
| NvFlexGetSmoothParticles(g_solver, g_buffers->smoothPositions.buffer, NULL); |
| NvFlexGetAnisotropy(g_solver, g_buffers->anisotropy1.buffer, g_buffers->anisotropy2.buffer, g_buffers->anisotropy3.buffer, NULL); |
|
|
| printf("Finished warm up.\n"); |
| } |
| } |
|
|
| void Reset() |
| { |
| Init(g_scene, false); |
| } |
|
|
| void Shutdown() |
| { |
| |
| DestroyBuffers(g_buffers); |
|
|
| for (auto& iter : g_meshes) |
| { |
| NvFlexDestroyTriangleMesh(g_flexLib, iter.first); |
| DestroyGpuMesh(iter.second); |
| } |
|
|
| for (auto& iter : g_fields) |
| { |
| NvFlexDestroyDistanceField(g_flexLib, iter.first); |
| DestroyGpuMesh(iter.second); |
| } |
|
|
| for (auto& iter : g_convexes) |
| { |
| NvFlexDestroyConvexMesh(g_flexLib, iter.first); |
| DestroyGpuMesh(iter.second); |
| } |
|
|
| g_fields.clear(); |
| g_meshes.clear(); |
|
|
| NvFlexDestroySolver(g_solver); |
| NvFlexShutdown(g_flexLib); |
|
|
| #if _WIN32 |
| if (g_ffmpeg) |
| _pclose(g_ffmpeg); |
| #endif |
| } |
|
|
| void UpdateEmitters() |
| { |
| float spin = DegToRad(15.0f); |
|
|
| const Vec3 forward(-sinf(g_camAngle.x + spin)*cosf(g_camAngle.y), sinf(g_camAngle.y), -cosf(g_camAngle.x + spin)*cosf(g_camAngle.y)); |
| const Vec3 right(Normalize(Cross(forward, Vec3(0.0f, 1.0f, 0.0f)))); |
|
|
| g_emitters[0].mDir = Normalize(forward + Vec3(0.0, 0.4f, 0.0f)); |
| g_emitters[0].mRight = right; |
| g_emitters[0].mPos = g_camPos + forward*1.f + Vec3(0.0f, 0.2f, 0.0f) + right*0.65f; |
|
|
| |
| if (g_emit) |
| { |
| int activeCount = NvFlexGetActiveCount(g_solver); |
|
|
| size_t e = 0; |
|
|
| |
| if (g_camSmoothVel.z >= 0.025f) |
| e = 1; |
|
|
| for (; e < g_emitters.size(); ++e) |
| { |
| if (!g_emitters[e].mEnabled) |
| continue; |
|
|
| Vec3 emitterDir = g_emitters[e].mDir; |
| Vec3 emitterRight = g_emitters[e].mRight; |
| Vec3 emitterPos = g_emitters[e].mPos; |
|
|
|
|
| float r = g_params.fluidRestDistance; |
| int phase = NvFlexMakePhase(0, eNvFlexPhaseSelfCollide | eNvFlexPhaseFluid); |
|
|
| float numParticles = (g_emitters[e].mSpeed / r)*g_dt; |
|
|
| |
| int n = int(numParticles + g_emitters[e].mLeftOver); |
|
|
| if (n) |
| g_emitters[e].mLeftOver = (numParticles + g_emitters[e].mLeftOver) - n; |
| else |
| g_emitters[e].mLeftOver += numParticles; |
|
|
| |
| for (int k = 0; k < n; ++k) |
| { |
| int emitterWidth = g_emitters[e].mWidth; |
| int numParticles = emitterWidth*emitterWidth; |
| for (int i = 0; i < numParticles; ++i) |
| { |
| float x = float(i%emitterWidth) - float(emitterWidth/2); |
| float y = float((i / emitterWidth) % emitterWidth) - float(emitterWidth/2); |
|
|
| if ((sqr(x) + sqr(y)) <= (emitterWidth / 2)*(emitterWidth / 2)) |
| { |
| Vec3 up = Normalize(Cross(emitterDir, emitterRight)); |
| Vec3 offset = r*(emitterRight*x + up*y) + float(k)*emitterDir*r; |
|
|
| if (activeCount < g_buffers->positions.size()) |
| { |
| g_buffers->positions[activeCount] = Vec4(emitterPos + offset, 1.0f); |
| g_buffers->velocities[activeCount] = emitterDir*g_emitters[e].mSpeed; |
| g_buffers->phases[activeCount] = phase; |
|
|
| g_buffers->activeIndices.push_back(activeCount); |
|
|
| activeCount++; |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
|
|
| void UpdateCamera() |
| { |
| Vec3 forward(-sinf(g_camAngle.x)*cosf(g_camAngle.y), sinf(g_camAngle.y), -cosf(g_camAngle.x)*cosf(g_camAngle.y)); |
| Vec3 right(Normalize(Cross(forward, Vec3(0.0f, 1.0f, 0.0f)))); |
|
|
| g_camSmoothVel = Lerp(g_camSmoothVel, g_camVel, 0.1f); |
| g_camPos += (forward*g_camSmoothVel.z + right*g_camSmoothVel.x + Cross(right, forward)*g_camSmoothVel.y); |
| } |
|
|
| void UpdateMouse() |
| { |
| |
| if (g_lastb == -1) |
| { |
| if (g_mouseParticle != -1) |
| { |
| |
| g_buffers->positions[g_mouseParticle].w = g_mouseMass; |
|
|
| |
| g_mouseParticle = -1; |
| } |
| } |
|
|
| |
| if (g_mousePicked) |
| { |
| assert(g_mouseParticle == -1); |
|
|
| Vec3 origin, dir; |
| GetViewRay(g_lastx, g_screenHeight - g_lasty, origin, dir); |
|
|
| const int numActive = NvFlexGetActiveCount(g_solver); |
|
|
| g_mouseParticle = PickParticle(origin, dir, &g_buffers->positions[0], &g_buffers->phases[0], numActive, g_params.radius*0.8f, g_mouseT); |
|
|
| if (g_mouseParticle != -1) |
| { |
| printf("picked: %d, mass: %f v: %f %f %f\n", g_mouseParticle, g_buffers->positions[g_mouseParticle].w, g_buffers->velocities[g_mouseParticle].x, g_buffers->velocities[g_mouseParticle].y, g_buffers->velocities[g_mouseParticle].z); |
|
|
| g_mousePos = origin + dir*g_mouseT; |
| g_mouseMass = g_buffers->positions[g_mouseParticle].w; |
| g_buffers->positions[g_mouseParticle].w = 0.0f; |
| } |
|
|
| g_mousePicked = false; |
| } |
|
|
| |
| if (g_mouseParticle != -1) |
| { |
| Vec3 p = Lerp(Vec3(g_buffers->positions[g_mouseParticle]), g_mousePos, 0.8f); |
| Vec3 delta = p - Vec3(g_buffers->positions[g_mouseParticle]); |
|
|
| g_buffers->positions[g_mouseParticle].x = p.x; |
| g_buffers->positions[g_mouseParticle].y = p.y; |
| g_buffers->positions[g_mouseParticle].z = p.z; |
|
|
| g_buffers->velocities[g_mouseParticle].x = delta.x / g_dt; |
| g_buffers->velocities[g_mouseParticle].y = delta.y / g_dt; |
| g_buffers->velocities[g_mouseParticle].z = delta.z / g_dt; |
| } |
| } |
|
|
| void UpdateWind() |
| { |
| g_windTime += g_dt; |
|
|
| const Vec3 kWindDir = Vec3(3.0f, 15.0f, 0.0f); |
| const float kNoise = Perlin1D(g_windTime*g_windFrequency, 10, 0.25f); |
| Vec3 wind = g_windStrength*kWindDir*Vec3(kNoise, fabsf(kNoise), 0.0f); |
|
|
| g_params.wind[0] = wind.x; |
| g_params.wind[1] = wind.y; |
| g_params.wind[2] = wind.z; |
|
|
| if (g_wavePool) |
| { |
| g_waveTime += g_dt; |
|
|
| g_params.planes[2][3] = g_wavePlane + (sinf(float(g_waveTime)*g_waveFrequency - kPi*0.5f)*0.5f + 0.5f)*g_waveAmplitude; |
| } |
| } |
|
|
| void SyncScene() |
| { |
| |
| g_scenes[g_scene]->Sync(); |
| } |
|
|
| void UpdateScene() |
| { |
| |
| g_scenes[g_scene]->Update(); |
| } |
|
|
| void RenderScene() |
| { |
| const int numParticles = NvFlexGetActiveCount(g_solver); |
| const int numDiffuse = g_buffers->diffuseCount[0]; |
|
|
| |
| |
| |
|
|
| if (numParticles) |
| { |
|
|
| if (g_interop) |
| { |
| |
| UpdateFluidRenderBuffers(g_fluidRenderBuffers, g_solver, g_drawEllipsoids, g_drawDensity); |
| } |
| else |
| { |
| |
|
|
| if (g_drawEllipsoids) |
| { |
| |
| UpdateFluidRenderBuffers(g_fluidRenderBuffers, |
| &g_buffers->smoothPositions[0], |
| (g_drawDensity) ? &g_buffers->densities[0] : (float*)&g_buffers->phases[0], |
| &g_buffers->anisotropy1[0], |
| &g_buffers->anisotropy2[0], |
| &g_buffers->anisotropy3[0], |
| g_buffers->positions.size(), |
| &g_buffers->activeIndices[0], |
| numParticles); |
| } |
| else |
| { |
| |
| UpdateFluidRenderBuffers(g_fluidRenderBuffers, |
| &g_buffers->positions[0], |
| (float*)&g_buffers->phases[0], |
| NULL, NULL, NULL, |
| g_buffers->positions.size(), |
| &g_buffers->activeIndices[0], |
| numParticles); |
| } |
| } |
| } |
|
|
| |
| GraphicsTimerBegin(); |
| |
| if (numDiffuse) |
| { |
| if (g_interop) |
| { |
| |
| UpdateDiffuseRenderBuffers(g_diffuseRenderBuffers, g_solver); |
| } |
| else |
| { |
| |
| UpdateDiffuseRenderBuffers(g_diffuseRenderBuffers, |
| &g_buffers->diffusePositions[0], |
| &g_buffers->diffuseVelocities[0], |
| numDiffuse); |
| } |
| } |
| |
| |
| |
|
|
| float fov = kPi / 4.0f; |
| float aspect = float(g_screenWidth) / g_screenHeight; |
|
|
| Matrix44 proj = ProjectionMatrix(RadToDeg(fov), aspect, g_camNear, g_camFar); |
| Matrix44 view = RotationMatrix(-g_camAngle.x, Vec3(0.0f, 1.0f, 0.0f))*RotationMatrix(-g_camAngle.y, Vec3(cosf(-g_camAngle.x), 0.0f, sinf(-g_camAngle.x)))*TranslationMatrix(-Point3(g_camPos)); |
|
|
| |
| |
|
|
| |
| g_sceneLower = Min(g_sceneLower, Vec3(-2.0f, 0.0f, -2.0f)); |
| g_sceneUpper = Max(g_sceneUpper, Vec3(2.0f, 2.0f, 2.0f)); |
|
|
| Vec3 sceneExtents = g_sceneUpper - g_sceneLower; |
| Vec3 sceneCenter = 0.5f*(g_sceneUpper + g_sceneLower); |
|
|
| g_lightDir = Normalize(Vec3(5.0f, 15.0f, 7.5f)); |
| g_lightPos = sceneCenter + g_lightDir*Length(sceneExtents)*g_lightDistance; |
| g_lightTarget = sceneCenter; |
|
|
| |
| float lightFov = 2.0f*atanf(Length(g_sceneUpper - sceneCenter) / Length(g_lightPos - sceneCenter)); |
|
|
| |
| lightFov = Clamp(lightFov, DegToRad(25.0f), DegToRad(65.0f)); |
|
|
| Matrix44 lightPerspective = ProjectionMatrix(RadToDeg(lightFov), 1.0f, 1.0f, 1000.0f); |
| Matrix44 lightView = LookAtMatrix(Point3(g_lightPos), Point3(g_lightTarget)); |
| Matrix44 lightTransform = lightPerspective*lightView; |
|
|
| |
| float radius = Max(g_params.solidRestDistance, g_params.fluidRestDistance)*0.5f*g_pointScale; |
|
|
| |
| |
|
|
| if (g_meshSkinIndices.size()) |
| SkinMesh(); |
|
|
| |
| ShadowBegin(g_shadowMap); |
|
|
| SetView(lightView, lightPerspective); |
| SetCullMode(false); |
|
|
| |
| g_scenes[g_scene]->Draw(1); |
|
|
| if (g_drawMesh) |
| DrawMesh(g_mesh, g_meshColor); |
|
|
| DrawShapes(); |
|
|
| if (g_drawCloth && g_buffers->triangles.size()) |
| { |
| DrawCloth(&g_buffers->positions[0], &g_buffers->normals[0], g_buffers->uvs.size() ? &g_buffers->uvs[0].x : NULL, &g_buffers->triangles[0], g_buffers->triangles.size() / 3, g_buffers->positions.size(), 3, g_expandCloth); |
| } |
|
|
| if (g_drawRopes) |
| { |
| for (size_t i = 0; i < g_ropes.size(); ++i) |
| DrawRope(&g_buffers->positions[0], &g_ropes[i].mIndices[0], g_ropes[i].mIndices.size(), radius*g_ropeScale, i); |
| } |
|
|
| int shadowParticles = numParticles; |
| int shadowParticlesOffset = 0; |
|
|
| if (!g_drawPoints) |
| { |
| shadowParticles = 0; |
|
|
| if (g_drawEllipsoids) |
| { |
| shadowParticles = numParticles - g_numSolidParticles; |
| shadowParticlesOffset = g_numSolidParticles; |
| } |
| } |
| else |
| { |
| int offset = g_drawMesh ? g_numSolidParticles : 0; |
|
|
| shadowParticles = numParticles - offset; |
| shadowParticlesOffset = offset; |
| } |
|
|
| if (g_buffers->activeIndices.size()) |
| DrawPoints(g_fluidRenderBuffers, shadowParticles, shadowParticlesOffset, radius, 2048, 1.0f, lightFov, g_lightPos, g_lightTarget, lightTransform, g_shadowMap, g_drawDensity); |
|
|
| ShadowEnd(); |
|
|
| |
| |
|
|
| BindSolidShader(g_lightPos, g_lightTarget, lightTransform, g_shadowMap, 0.0f, Vec4(g_clearColor, g_fogDistance)); |
|
|
| SetView(view, proj); |
| SetCullMode(true); |
|
|
| |
| |
| int passes = g_increaseGfxLoadForAsyncComputeTesting ? 50 : 1; |
|
|
| for (int i = 0; i != passes; i++) |
| { |
|
|
| DrawPlanes((Vec4*)g_params.planes, g_params.numPlanes, g_drawPlaneBias); |
|
|
| if (g_drawMesh) |
| DrawMesh(g_mesh, g_meshColor); |
|
|
|
|
| DrawShapes(); |
|
|
| if (g_drawCloth && g_buffers->triangles.size()) |
| DrawCloth(&g_buffers->positions[0], &g_buffers->normals[0], g_buffers->uvs.size() ? &g_buffers->uvs[0].x : NULL, &g_buffers->triangles[0], g_buffers->triangles.size() / 3, g_buffers->positions.size(), 3, g_expandCloth); |
|
|
| if (g_drawRopes) |
| { |
| for (size_t i = 0; i < g_ropes.size(); ++i) |
| DrawRope(&g_buffers->positions[0], &g_ropes[i].mIndices[0], g_ropes[i].mIndices.size(), g_params.radius*0.5f*g_ropeScale, i); |
| } |
|
|
| |
| g_scenes[g_scene]->Draw(0); |
| } |
| UnbindSolidShader(); |
|
|
|
|
| |
| if (g_drawDiffuse) |
| RenderDiffuse(g_fluidRenderer, g_diffuseRenderBuffers, numDiffuse, radius*g_diffuseScale, float(g_screenWidth), aspect, fov, g_diffuseColor, g_lightPos, g_lightTarget, lightTransform, g_shadowMap, g_diffuseMotionScale, g_diffuseInscatter, g_diffuseOutscatter, g_diffuseShadow, false); |
|
|
| if (g_drawEllipsoids) |
| { |
| |
| if (g_numSolidParticles && g_drawPoints) |
| DrawPoints(g_fluidRenderBuffers, g_numSolidParticles, 0, radius, float(g_screenWidth), aspect, fov, g_lightPos, g_lightTarget, lightTransform, g_shadowMap, g_drawDensity); |
|
|
| |
| RenderEllipsoids(g_fluidRenderer, g_fluidRenderBuffers, numParticles - g_numSolidParticles, g_numSolidParticles, radius, float(g_screenWidth), aspect, fov, g_lightPos, g_lightTarget, lightTransform, g_shadowMap, g_fluidColor, g_blur, g_ior, g_drawOpaque); |
|
|
| |
| if (g_drawDiffuse) |
| RenderDiffuse(g_fluidRenderer, g_diffuseRenderBuffers, numDiffuse, radius*g_diffuseScale, float(g_screenWidth), aspect, fov, g_diffuseColor, g_lightPos, g_lightTarget, lightTransform, g_shadowMap, g_diffuseMotionScale, g_diffuseInscatter, g_diffuseOutscatter, g_diffuseShadow, true); |
| } |
| else |
| { |
| |
| if (g_drawPoints) |
| { |
| int offset = g_drawMesh ? g_numSolidParticles : 0; |
|
|
| if (g_buffers->activeIndices.size()) |
| DrawPoints(g_fluidRenderBuffers, numParticles - offset, offset, radius, float(g_screenWidth), aspect, fov, g_lightPos, g_lightTarget, lightTransform, g_shadowMap, g_drawDensity); |
| } |
| } |
|
|
| GraphicsTimerEnd(); |
| } |
|
|
| void RenderDebug() |
| { |
| if (g_mouseParticle != -1) |
| { |
| |
| BeginLines(); |
| DrawLine(g_mousePos, Vec3(g_buffers->positions[g_mouseParticle]), Vec4(1.0f)); |
| EndLines(); |
| } |
|
|
| |
| if (g_drawSprings) |
| { |
| Vec4 color; |
|
|
| if (g_drawSprings == 1) |
| { |
| |
| color = Vec4(0.0f, 0.0f, 1.0f, 0.8f); |
| } |
| if (g_drawSprings == 2) |
| { |
| |
| color = Vec4(0.0f, 1.0f, 0.0f, 0.8f); |
| } |
|
|
| BeginLines(); |
|
|
| int start = 0; |
|
|
| for (int i = start; i < g_buffers->springLengths.size(); ++i) |
| { |
| if (g_drawSprings == 1 && g_buffers->springStiffness[i] < 0.0f) |
| continue; |
| if (g_drawSprings == 2 && g_buffers->springStiffness[i] > 0.0f) |
| continue; |
|
|
| int a = g_buffers->springIndices[i * 2]; |
| int b = g_buffers->springIndices[i * 2 + 1]; |
|
|
| DrawLine(Vec3(g_buffers->positions[a]), Vec3(g_buffers->positions[b]), color); |
| } |
|
|
| EndLines(); |
| } |
|
|
| |
| if (g_drawContacts) |
| { |
| const int maxContactsPerParticle = 6; |
|
|
| NvFlexVector<Vec4> contactPlanes(g_flexLib, g_buffers->positions.size()*maxContactsPerParticle); |
| NvFlexVector<Vec4> contactVelocities(g_flexLib, g_buffers->positions.size()*maxContactsPerParticle); |
| NvFlexVector<int> contactIndices(g_flexLib, g_buffers->positions.size()); |
| NvFlexVector<unsigned int> contactCounts(g_flexLib, g_buffers->positions.size()); |
|
|
| NvFlexGetContacts(g_solver, contactPlanes.buffer, contactVelocities.buffer, contactIndices.buffer, contactCounts.buffer); |
|
|
| |
| contactPlanes.map(); |
| contactVelocities.map(); |
| contactIndices.map(); |
| contactCounts.map(); |
|
|
| BeginLines(); |
|
|
| for (int i = 0; i < int(g_buffers->activeIndices.size()); ++i) |
| { |
| const int contactIndex = contactIndices[g_buffers->activeIndices[i]]; |
| const unsigned int count = contactCounts[contactIndex]; |
|
|
| const float scale = 0.1f; |
|
|
| for (unsigned int c = 0; c < count; ++c) |
| { |
| Vec4 plane = contactPlanes[contactIndex*maxContactsPerParticle + c]; |
|
|
| DrawLine(Vec3(g_buffers->positions[g_buffers->activeIndices[i]]), |
| Vec3(g_buffers->positions[g_buffers->activeIndices[i]]) + Vec3(plane)*scale, |
| Vec4(0.0f, 1.0f, 0.0f, 0.0f)); |
| } |
| } |
|
|
| EndLines(); |
| } |
| |
| if (g_drawBases) |
| { |
| for (int i = 0; i < int(g_buffers->rigidRotations.size()); ++i) |
| { |
| BeginLines(); |
|
|
| float size = 0.1f; |
|
|
| for (int b = 0; b < 3; ++b) |
| { |
| Vec3 color; |
| color[b] = 1.0f; |
| |
| Matrix33 frame(g_buffers->rigidRotations[i]); |
|
|
| DrawLine(Vec3(g_buffers->rigidTranslations[i]), |
| Vec3(g_buffers->rigidTranslations[i] + frame.cols[b] * size), |
| Vec4(color, 0.0f)); |
| } |
|
|
| EndLines(); |
| } |
| } |
|
|
| if (g_drawNormals) |
| { |
| NvFlexGetNormals(g_solver, g_buffers->normals.buffer, NULL); |
|
|
| BeginLines(); |
|
|
| for (int i = 0; i < g_buffers->normals.size(); ++i) |
| { |
| DrawLine(Vec3(g_buffers->positions[i]), |
| Vec3(g_buffers->positions[i] - g_buffers->normals[i] * g_buffers->normals[i].w), |
| Vec4(0.0f, 1.0f, 0.0f, 0.0f)); |
| } |
|
|
| EndLines(); |
| } |
| } |
|
|
| void DrawShapes() |
| { |
| for (int i = 0; i < g_buffers->shapeFlags.size(); ++i) |
| { |
| const int flags = g_buffers->shapeFlags[i]; |
|
|
| |
| int type = int(flags&eNvFlexShapeFlagTypeMask); |
| |
|
|
| Vec3 color = Vec3(0.9f); |
|
|
| if (flags & eNvFlexShapeFlagTrigger) |
| { |
| color = Vec3(0.6f, 1.0, 0.6f); |
|
|
| SetFillMode(true); |
| } |
|
|
| |
| |
| const Quat rotation = g_buffers->shapePrevRotations[i]; |
| const Vec3 position = Vec3(g_buffers->shapePrevPositions[i]); |
|
|
| NvFlexCollisionGeometry geo = g_buffers->shapeGeometry[i]; |
|
|
| if (type == eNvFlexShapeSphere) |
| { |
| Mesh* sphere = CreateSphere(20, 20, geo.sphere.radius); |
|
|
| Matrix44 xform = TranslationMatrix(Point3(position))*RotationMatrix(Quat(rotation)); |
| sphere->Transform(xform); |
|
|
| DrawMesh(sphere, Vec3(color)); |
|
|
| delete sphere; |
| } |
| else if (type == eNvFlexShapeCapsule) |
| { |
| Mesh* capsule = CreateCapsule(10, 20, geo.capsule.radius, geo.capsule.halfHeight); |
|
|
| |
| Matrix44 xform = TranslationMatrix(Point3(position))*RotationMatrix(Quat(rotation))*RotationMatrix(DegToRad(-90.0f), Vec3(0.0f, 0.0f, 1.0f)); |
| capsule->Transform(xform); |
|
|
| DrawMesh(capsule, Vec3(color)); |
|
|
| delete capsule; |
| } |
| else if (type == eNvFlexShapeBox) |
| { |
| Mesh* box = CreateCubeMesh(); |
|
|
| Matrix44 xform = TranslationMatrix(Point3(position))*RotationMatrix(Quat(rotation))*ScaleMatrix(Vec3(geo.box.halfExtents)*2.0f); |
| box->Transform(xform); |
|
|
| DrawMesh(box, Vec3(color)); |
| delete box; |
| } |
| else if (type == eNvFlexShapeConvexMesh) |
| { |
| if (g_convexes.find(geo.convexMesh.mesh) != g_convexes.end()) |
| { |
| GpuMesh* m = g_convexes[geo.convexMesh.mesh]; |
|
|
| if (m) |
| { |
| Matrix44 xform = TranslationMatrix(Point3(g_buffers->shapePositions[i]))*RotationMatrix(Quat(g_buffers->shapeRotations[i]))*ScaleMatrix(geo.convexMesh.scale); |
| DrawGpuMesh(m, xform, Vec3(color)); |
| } |
| } |
| } |
| else if (type == eNvFlexShapeTriangleMesh) |
| { |
| if (g_meshes.find(geo.triMesh.mesh) != g_meshes.end()) |
| { |
| GpuMesh* m = g_meshes[geo.triMesh.mesh]; |
|
|
| if (m) |
| { |
| Matrix44 xform = TranslationMatrix(Point3(position))*RotationMatrix(Quat(rotation))*ScaleMatrix(geo.triMesh.scale); |
| DrawGpuMesh(m, xform, Vec3(color)); |
| } |
| } |
| } |
| else if (type == eNvFlexShapeSDF) |
| { |
| if (g_fields.find(geo.sdf.field) != g_fields.end()) |
| { |
| GpuMesh* m = g_fields[geo.sdf.field]; |
|
|
| if (m) |
| { |
| Matrix44 xform = TranslationMatrix(Point3(position))*RotationMatrix(Quat(rotation))*ScaleMatrix(geo.sdf.scale); |
| DrawGpuMesh(m, xform, Vec3(color)); |
| } |
| } |
| } |
| } |
|
|
| SetFillMode(g_wireframe); |
| } |
|
|
|
|
| |
| int DoUI() |
| { |
| |
| int newScene = -1; |
|
|
| if (g_showHelp) |
| { |
| const int numParticles = NvFlexGetActiveCount(g_solver); |
| const int numDiffuse = g_buffers->diffuseCount[0]; |
|
|
| int x = g_screenWidth - 200; |
| int y = g_screenHeight - 23; |
|
|
| |
| unsigned char button = 0; |
| if (g_lastb == SDL_BUTTON_LEFT) |
| button = IMGUI_MBUT_LEFT; |
| else if (g_lastb == SDL_BUTTON_RIGHT) |
| button = IMGUI_MBUT_RIGHT; |
|
|
| imguiBeginFrame(g_lastx, g_screenHeight - g_lasty, button, 0); |
|
|
| x += 180; |
|
|
| int fontHeight = 13; |
|
|
| if (1) |
| { |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Frame: %d", g_frame); y -= fontHeight * 2; |
|
|
| if (!g_ffmpeg) |
| { |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Frame Time: %.2fms", g_realdt*1000.0f); y -= fontHeight * 2; |
|
|
| |
| if (!g_profile) |
| { |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Sim Time (CPU): %.2fms", g_updateTime*1000.0f); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(0.97f, 0.59f, 0.27f), IMGUI_ALIGN_RIGHT, "Sim Latency (GPU): %.2fms", g_simLatency); y -= fontHeight * 2; |
|
|
| BenchmarkUpdateGraph(); |
| } |
| else |
| { |
| y -= fontHeight * 3; |
| } |
| } |
|
|
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Particle Count: %d", numParticles); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Diffuse Count: %d", numDiffuse); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Rigid Count: %d", g_buffers->rigidOffsets.size() > 0 ? g_buffers->rigidOffsets.size() - 1 : 0); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Spring Count: %d", g_buffers->springLengths.size()); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Num Substeps: %d", g_numSubsteps); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Num Iterations: %d", g_params.numIterations); y -= fontHeight * 2; |
|
|
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Device: %s", g_deviceName); y -= fontHeight * 2; |
| } |
|
|
| if (g_profile) |
| { |
| DrawImguiString(x, y, Vec3(0.97f, 0.59f, 0.27f), IMGUI_ALIGN_RIGHT, "Total GPU Sim Latency: %.2fms", g_timers.total); y -= fontHeight * 2; |
|
|
| DrawImguiString(x, y, Vec3(0.0f, 1.0f, 0.0f), IMGUI_ALIGN_RIGHT, "GPU Latencies"); y -= fontHeight; |
|
|
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Predict: %.2fms", g_timers.predict); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Create Cell Indices: %.2fms", g_timers.createCellIndices); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Sort Cell Indices: %.2fms", g_timers.sortCellIndices); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Reorder: %.2fms", g_timers.reorder); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "CreateGrid: %.2fms", g_timers.createGrid); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Collide Particles: %.2fms", g_timers.collideParticles); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Collide Shapes: %.2fms", g_timers.collideShapes); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Collide Triangles: %.2fms", g_timers.collideTriangles); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Calculate Density: %.2fms", g_timers.calculateDensity); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Solve Densities: %.2fms", g_timers.solveDensities); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Solve Velocities: %.2fms", g_timers.solveVelocities); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Solve Rigids: %.2fms", g_timers.solveShapes); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Solve Springs: %.2fms", g_timers.solveSprings); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Solve Inflatables: %.2fms", g_timers.solveInflatables); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Solve Contacts: %.2fms", g_timers.solveContacts); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Apply Deltas: %.2fms", g_timers.applyDeltas); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Finalize: %.2fms", g_timers.finalize); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Update Triangles: %.2fms", g_timers.updateTriangles); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Update Normals: %.2fms", g_timers.updateNormals); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Update Bounds: %.2fms", g_timers.updateBounds); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Calculate Anisotropy: %.2fms", g_timers.calculateAnisotropy); y -= fontHeight; |
| DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Update Diffuse: %.2fms", g_timers.updateDiffuse); y -= fontHeight * 2; |
| } |
|
|
| x -= 180; |
|
|
| int uiOffset = 250; |
| int uiBorder = 20; |
| int uiWidth = 200; |
| int uiHeight = g_screenHeight - uiOffset - uiBorder * 3; |
| int uiLeft = uiBorder; |
|
|
| if (g_tweakPanel) |
| imguiBeginScrollArea("Scene", uiLeft, g_screenHeight - uiBorder - uiOffset, uiWidth, uiOffset, &g_levelScroll); |
| else |
| imguiBeginScrollArea("Scene", uiLeft, uiBorder, uiWidth, g_screenHeight - uiBorder - uiBorder, &g_levelScroll); |
|
|
| for (int i = 0; i < int(g_scenes.size()); ++i) |
| { |
| unsigned int color = g_scene == i ? imguiRGBA(255, 151, 61, 255) : imguiRGBA(255, 255, 255, 200); |
| if (imguiItem(g_scenes[i]->GetName(), true, color)) |
| { |
| newScene = i; |
| } |
| } |
|
|
| imguiEndScrollArea(); |
|
|
| if (g_tweakPanel) |
| { |
| static int scroll = 0; |
|
|
| imguiBeginScrollArea("Options", uiLeft, g_screenHeight - uiBorder - uiHeight - uiOffset - uiBorder, uiWidth, uiHeight, &scroll); |
| imguiSeparatorLine(); |
|
|
| |
| imguiLabel("Global"); |
| if (imguiCheck("Emit particles", g_emit)) |
| g_emit = !g_emit; |
|
|
| if (imguiCheck("Pause", g_pause)) |
| g_pause = !g_pause; |
|
|
| imguiSeparatorLine(); |
|
|
| if (imguiCheck("Wireframe", g_wireframe)) |
| g_wireframe = !g_wireframe; |
|
|
| if (imguiCheck("Draw Points", g_drawPoints)) |
| g_drawPoints = !g_drawPoints; |
|
|
| if (imguiCheck("Draw Fluid", g_drawEllipsoids)) |
| g_drawEllipsoids = !g_drawEllipsoids; |
|
|
| if (imguiCheck("Draw Mesh", g_drawMesh)) |
| { |
| g_drawMesh = !g_drawMesh; |
| g_drawRopes = !g_drawRopes; |
| } |
|
|
| if (imguiCheck("Draw Basis", g_drawBases)) |
| g_drawBases = !g_drawBases; |
|
|
| if (imguiCheck("Draw Springs", bool(g_drawSprings != 0))) |
| g_drawSprings = (g_drawSprings) ? 0 : 1; |
|
|
| if (imguiCheck("Draw Contacts", g_drawContacts)) |
| g_drawContacts = !g_drawContacts; |
|
|
| imguiSeparatorLine(); |
|
|
| |
| g_scenes[g_scene]->DoGui(); |
|
|
| if (imguiButton("Reset Scene")) |
| g_resetScene = true; |
|
|
| imguiSeparatorLine(); |
|
|
| float n = float(g_numSubsteps); |
| if (imguiSlider("Num Substeps", &n, 1, 10, 1)) |
| g_numSubsteps = int(n); |
|
|
| n = float(g_params.numIterations); |
| if (imguiSlider("Num Iterations", &n, 1, 20, 1)) |
| g_params.numIterations = int(n); |
|
|
| imguiSeparatorLine(); |
| imguiSlider("Gravity X", &g_params.gravity[0], -50.0f, 50.0f, 1.0f); |
| imguiSlider("Gravity Y", &g_params.gravity[1], -50.0f, 50.0f, 1.0f); |
| imguiSlider("Gravity Z", &g_params.gravity[2], -50.0f, 50.0f, 1.0f); |
|
|
| imguiSeparatorLine(); |
| imguiSlider("Radius", &g_params.radius, 0.01f, 0.5f, 0.01f); |
| imguiSlider("Solid Radius", &g_params.solidRestDistance, 0.0f, 0.5f, 0.001f); |
| imguiSlider("Fluid Radius", &g_params.fluidRestDistance, 0.0f, 0.5f, 0.001f); |
|
|
| |
| imguiSeparatorLine(); |
| imguiSlider("Dynamic Friction", &g_params.dynamicFriction, 0.0f, 1.0f, 0.01f); |
| imguiSlider("Static Friction", &g_params.staticFriction, 0.0f, 1.0f, 0.01f); |
| imguiSlider("Particle Friction", &g_params.particleFriction, 0.0f, 1.0f, 0.01f); |
| imguiSlider("Restitution", &g_params.restitution, 0.0f, 1.0f, 0.01f); |
| imguiSlider("SleepThreshold", &g_params.sleepThreshold, 0.0f, 1.0f, 0.01f); |
| imguiSlider("Shock Propagation", &g_params.shockPropagation, 0.0f, 10.0f, 0.01f); |
| imguiSlider("Damping", &g_params.damping, 0.0f, 10.0f, 0.01f); |
| imguiSlider("Dissipation", &g_params.dissipation, 0.0f, 0.01f, 0.0001f); |
| imguiSlider("SOR", &g_params.relaxationFactor, 0.0f, 5.0f, 0.01f); |
|
|
| imguiSlider("Collision Distance", &g_params.collisionDistance, 0.0f, 0.5f, 0.001f); |
| imguiSlider("Collision Margin", &g_params.shapeCollisionMargin, 0.0f, 5.0f, 0.01f); |
|
|
| |
| imguiSeparatorLine(); |
| imguiSlider("Wind", &g_windStrength, -1.0f, 1.0f, 0.01f); |
| imguiSlider("Drag", &g_params.drag, 0.0f, 1.0f, 0.01f); |
| imguiSlider("Lift", &g_params.lift, 0.0f, 1.0f, 0.01f); |
| imguiSeparatorLine(); |
|
|
| |
| imguiSlider("Adhesion", &g_params.adhesion, 0.0f, 10.0f, 0.01f); |
| imguiSlider("Cohesion", &g_params.cohesion, 0.0f, 0.2f, 0.0001f); |
| imguiSlider("Surface Tension", &g_params.surfaceTension, 0.0f, 50.0f, 0.01f); |
| imguiSlider("Viscosity", &g_params.viscosity, 0.0f, 120.0f, 0.01f); |
| imguiSlider("Vorticicty Confinement", &g_params.vorticityConfinement, 0.0f, 120.0f, 0.1f); |
| imguiSlider("Solid Pressure", &g_params.solidPressure, 0.0f, 1.0f, 0.01f); |
| imguiSlider("Surface Drag", &g_params.freeSurfaceDrag, 0.0f, 1.0f, 0.01f); |
| imguiSlider("Buoyancy", &g_params.buoyancy, -1.0f, 1.0f, 0.01f); |
|
|
| imguiSeparatorLine(); |
| imguiSlider("Anisotropy Scale", &g_params.anisotropyScale, 0.0f, 30.0f, 0.01f); |
| imguiSlider("Smoothing", &g_params.smoothing, 0.0f, 1.0f, 0.01f); |
|
|
| |
| imguiSeparatorLine(); |
| imguiSlider("Diffuse Threshold", &g_params.diffuseThreshold, 0.0f, 1000.0f, 1.0f); |
| imguiSlider("Diffuse Buoyancy", &g_params.diffuseBuoyancy, 0.0f, 2.0f, 0.01f); |
| imguiSlider("Diffuse Drag", &g_params.diffuseDrag, 0.0f, 2.0f, 0.01f); |
| imguiSlider("Diffuse Scale", &g_diffuseScale, 0.0f, 1.5f, 0.01f); |
| imguiSlider("Diffuse Alpha", &g_diffuseColor.w, 0.0f, 3.0f, 0.01f); |
| imguiSlider("Diffuse Inscatter", &g_diffuseInscatter, 0.0f, 2.0f, 0.01f); |
| imguiSlider("Diffuse Outscatter", &g_diffuseOutscatter, 0.0f, 2.0f, 0.01f); |
| imguiSlider("Diffuse Motion Blur", &g_diffuseMotionScale, 0.0f, 5.0f, 0.1f); |
|
|
| n = float(g_params.diffuseBallistic); |
| if (imguiSlider("Diffuse Ballistic", &n, 1, 40, 1)) |
| g_params.diffuseBallistic = int(n); |
|
|
| imguiEndScrollArea(); |
| } |
| imguiEndFrame(); |
|
|
| |
| DrawImguiGraph(); |
| } |
|
|
| return newScene; |
| } |
|
|
| void UpdateFrame() |
| { |
| static double lastTime; |
|
|
| |
| double frameBeginTime = GetSeconds(); |
|
|
| g_realdt = float(frameBeginTime - lastTime); |
| lastTime = frameBeginTime; |
|
|
| |
| double currentTime = frameBeginTime; |
| static double lastJoyTime = currentTime; |
|
|
| if (g_gamecontroller && currentTime - lastJoyTime > g_dt) |
| { |
| lastJoyTime = currentTime; |
|
|
| int leftStickX = SDL_GameControllerGetAxis(g_gamecontroller, SDL_CONTROLLER_AXIS_LEFTX); |
| int leftStickY = SDL_GameControllerGetAxis(g_gamecontroller, SDL_CONTROLLER_AXIS_LEFTY); |
| int rightStickX = SDL_GameControllerGetAxis(g_gamecontroller, SDL_CONTROLLER_AXIS_RIGHTX); |
| int rightStickY = SDL_GameControllerGetAxis(g_gamecontroller, SDL_CONTROLLER_AXIS_RIGHTY); |
| int leftTrigger = SDL_GameControllerGetAxis(g_gamecontroller, SDL_CONTROLLER_AXIS_TRIGGERLEFT); |
| int rightTrigger = SDL_GameControllerGetAxis(g_gamecontroller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT); |
|
|
| Vec2 leftStick(joyAxisFilter(leftStickX, 0), joyAxisFilter(leftStickY, 0)); |
| Vec2 rightStick(joyAxisFilter(rightStickX, 1), joyAxisFilter(rightStickY, 1)); |
| Vec2 trigger(leftTrigger / 32768.0f, rightTrigger / 32768.0f); |
|
|
| if (leftStick.x != 0.0f || leftStick.y != 0.0f || |
| rightStick.x != 0.0f || rightStick.y != 0.0f) |
| { |
| |
| g_camVel.z = -4 * g_camSpeed * leftStick.y; |
| g_camVel.x = 4 * g_camSpeed * leftStick.x; |
|
|
| |
| g_camAngle.x -= rightStick.x * 0.05f; |
| g_camAngle.y -= rightStick.y * 0.05f; |
| } |
|
|
| |
| static bool bLeftStick = false; |
|
|
| if ((leftStick.x != 0.0f || leftStick.y != 0.0f) && !bLeftStick) |
| { |
| bLeftStick = true; |
| } |
| else if ((leftStick.x == 0.0f && leftStick.y == 0.0f) && bLeftStick) |
| { |
| bLeftStick = false; |
| g_camVel.z = -4 * g_camSpeed * leftStick.y; |
| g_camVel.x = 4 * g_camSpeed * leftStick.x; |
| } |
|
|
| |
| void ControllerButtonEvent(SDL_ControllerButtonEvent event); |
|
|
| static bool bLeftTrigger = false; |
| static bool bRightTrigger = false; |
| SDL_ControllerButtonEvent e; |
|
|
| if (!bLeftTrigger && trigger.x > 0.0f) |
| { |
| e.type = SDL_CONTROLLERBUTTONDOWN; |
| e.button = SDL_CONTROLLER_BUTTON_LEFT_TRIGGER; |
| ControllerButtonEvent(e); |
| bLeftTrigger = true; |
| } |
| else if (bLeftTrigger && trigger.x == 0.0f) |
| { |
| e.type = SDL_CONTROLLERBUTTONUP; |
| e.button = SDL_CONTROLLER_BUTTON_LEFT_TRIGGER; |
| ControllerButtonEvent(e); |
| bLeftTrigger = false; |
| } |
|
|
| if (!bRightTrigger && trigger.y > 0.0f) |
| { |
| e.type = SDL_CONTROLLERBUTTONDOWN; |
| e.button = SDL_CONTROLLER_BUTTON_RIGHT_TRIGGER; |
| ControllerButtonEvent(e); |
| bRightTrigger = true; |
| } |
| else if (bRightTrigger && trigger.y == 0.0f) |
| { |
| e.type = SDL_CONTROLLERBUTTONDOWN; |
| e.button = SDL_CONTROLLER_BUTTON_RIGHT_TRIGGER; |
| ControllerButtonEvent(e); |
| bRightTrigger = false; |
| } |
| } |
|
|
| |
| |
|
|
| double waitBeginTime = GetSeconds(); |
|
|
| MapBuffers(g_buffers); |
|
|
| double waitEndTime = GetSeconds(); |
|
|
| |
| float newSimLatency = NvFlexGetDeviceLatency(g_solver, &g_GpuTimers.computeBegin, &g_GpuTimers.computeEnd, &g_GpuTimers.computeFreq); |
| float newGfxLatency = RendererGetDeviceTimestamps(&g_GpuTimers.renderBegin, &g_GpuTimers.renderEnd, &g_GpuTimers.renderFreq); |
| (void)newGfxLatency; |
|
|
| UpdateCamera(); |
|
|
| if (!g_pause || g_step) |
| { |
| UpdateEmitters(); |
| UpdateMouse(); |
| UpdateWind(); |
| UpdateScene(); |
| } |
|
|
| |
| |
|
|
| double renderBeginTime = GetSeconds(); |
|
|
| if (g_profile && (!g_pause || g_step)) |
| { |
| if (g_benchmark) |
| { |
| g_numDetailTimers = NvFlexGetDetailTimers(g_solver, &g_detailTimers); |
| } |
| else |
| { |
| memset(&g_timers, 0, sizeof(g_timers)); |
| NvFlexGetTimers(g_solver, &g_timers); |
| } |
| } |
|
|
| StartFrame(Vec4(g_clearColor, 1.0f)); |
|
|
| |
| RenderScene(); |
| RenderDebug(); |
|
|
| int newScene = DoUI(); |
|
|
| EndFrame(); |
|
|
| |
| |
| if (!g_useAsyncCompute) |
| NvFlexComputeWaitForGraphics(g_flexLib); |
|
|
| UnmapBuffers(g_buffers); |
|
|
| |
| if (g_mouseParticle != -1) |
| { |
| Vec3 origin, dir; |
| GetViewRay(g_lastx, g_screenHeight - g_lasty, origin, dir); |
|
|
| g_mousePos = origin + dir*g_mouseT; |
| } |
|
|
| if (g_capture) |
| { |
| TgaImage img; |
| img.m_width = g_screenWidth; |
| img.m_height = g_screenHeight; |
| img.m_data = new uint32_t[g_screenWidth*g_screenHeight]; |
|
|
| ReadFrame((int*)img.m_data, g_screenWidth, g_screenHeight); |
|
|
| fwrite(img.m_data, sizeof(uint32_t)*g_screenWidth*g_screenHeight, 1, g_ffmpeg); |
|
|
| delete[] img.m_data; |
| } |
|
|
| double renderEndTime = GetSeconds(); |
|
|
| |
| if (g_resetScene) |
| { |
| Reset(); |
| g_resetScene = false; |
| } |
|
|
| |
| |
|
|
| double updateBeginTime = GetSeconds(); |
|
|
| |
| NvFlexSetParticles(g_solver, g_buffers->positions.buffer, NULL); |
| NvFlexSetVelocities(g_solver, g_buffers->velocities.buffer, NULL); |
| NvFlexSetPhases(g_solver, g_buffers->phases.buffer, NULL); |
| NvFlexSetActive(g_solver, g_buffers->activeIndices.buffer, NULL); |
|
|
| NvFlexSetActiveCount(g_solver, g_buffers->activeIndices.size()); |
|
|
| |
| SyncScene(); |
|
|
| if (g_shapesChanged) |
| { |
| NvFlexSetShapes( |
| g_solver, |
| g_buffers->shapeGeometry.buffer, |
| g_buffers->shapePositions.buffer, |
| g_buffers->shapeRotations.buffer, |
| g_buffers->shapePrevPositions.buffer, |
| g_buffers->shapePrevRotations.buffer, |
| g_buffers->shapeFlags.buffer, |
| int(g_buffers->shapeFlags.size())); |
|
|
| g_shapesChanged = false; |
| } |
|
|
| if (!g_pause || g_step) |
| { |
| |
| NvFlexSetParams(g_solver, &g_params); |
| NvFlexUpdateSolver(g_solver, g_dt, g_numSubsteps, g_profile); |
|
|
| g_frame++; |
| g_step = false; |
| } |
|
|
| |
| |
| |
| |
| |
| NvFlexGetParticles(g_solver, g_buffers->positions.buffer, NULL); |
| NvFlexGetVelocities(g_solver, g_buffers->velocities.buffer, NULL); |
| NvFlexGetNormals(g_solver, g_buffers->normals.buffer, NULL); |
|
|
| |
| if (g_buffers->triangles.size()) |
| NvFlexGetDynamicTriangles(g_solver, g_buffers->triangles.buffer, g_buffers->triangleNormals.buffer, g_buffers->triangles.size() / 3); |
|
|
| |
| if (g_buffers->rigidOffsets.size()) |
| NvFlexGetRigids(g_solver, NULL, NULL, NULL, NULL, NULL, NULL, NULL, g_buffers->rigidRotations.buffer, g_buffers->rigidTranslations.buffer); |
|
|
| if (!g_interop) |
| { |
| |
| if (g_drawEllipsoids) |
| { |
| NvFlexGetSmoothParticles(g_solver, g_buffers->smoothPositions.buffer, NULL); |
| NvFlexGetAnisotropy(g_solver, g_buffers->anisotropy1.buffer, g_buffers->anisotropy2.buffer, g_buffers->anisotropy3.buffer, NULL); |
| } |
|
|
| |
| if (g_drawDensity) |
| NvFlexGetDensities(g_solver, g_buffers->densities.buffer, NULL); |
|
|
| if (GetNumDiffuseRenderParticles(g_diffuseRenderBuffers)) |
| { |
| NvFlexGetDiffuseParticles(g_solver, g_buffers->diffusePositions.buffer, g_buffers->diffuseVelocities.buffer, g_buffers->diffuseCount.buffer); |
| } |
| } |
| else |
| { |
| |
| NvFlexGetDiffuseParticles(g_solver, NULL, NULL, g_buffers->diffuseCount.buffer); |
| } |
|
|
| double updateEndTime = GetSeconds(); |
|
|
| |
| |
|
|
| float newUpdateTime = float(updateEndTime - updateBeginTime); |
| float newRenderTime = float(renderEndTime - renderBeginTime); |
| float newWaitTime = float(waitBeginTime - waitEndTime); |
|
|
| |
| const float timerSmoothing = 0.05f; |
|
|
| g_updateTime = (g_updateTime == 0.0f) ? newUpdateTime : Lerp(g_updateTime, newUpdateTime, timerSmoothing); |
| g_renderTime = (g_renderTime == 0.0f) ? newRenderTime : Lerp(g_renderTime, newRenderTime, timerSmoothing); |
| g_waitTime = (g_waitTime == 0.0f) ? newWaitTime : Lerp(g_waitTime, newWaitTime, timerSmoothing); |
| g_simLatency = (g_simLatency == 0.0f) ? newSimLatency : Lerp(g_simLatency, newSimLatency, timerSmoothing); |
|
|
| if (g_benchmark) newScene = BenchmarkUpdate(); |
|
|
| |
| |
| PresentFrame(g_vsync); |
|
|
| |
| if (newScene != -1) |
| { |
| g_scene = newScene; |
| Init(g_scene); |
| } |
| } |
|
|
| #if ENABLE_AFTERMATH_SUPPORT |
| void DumpAftermathData() |
| { |
| GFSDK_Aftermath_ContextData dataOut; |
| GFSDK_Aftermath_Status statusOut; |
|
|
| NvFlexGetDataAftermath(g_flexLib, &dataOut, &statusOut); |
| wprintf(L"Last Aftermath event: %s\n", (wchar_t *)dataOut.markerData); |
| } |
| #endif |
|
|
| void ReshapeWindow(int width, int height) |
| { |
| if (!g_benchmark) |
| printf("Reshaping\n"); |
|
|
| ReshapeRender(g_window); |
|
|
| if (!g_fluidRenderer || (width != g_screenWidth || height != g_screenHeight)) |
| { |
| if (g_fluidRenderer) |
| DestroyFluidRenderer(g_fluidRenderer); |
| g_fluidRenderer = CreateFluidRenderer(width, height); |
| } |
|
|
| g_screenWidth = width; |
| g_screenHeight = height; |
| } |
|
|
| void InputArrowKeysDown(int key, int x, int y) |
| { |
| switch (key) |
| { |
| case SDLK_DOWN: |
| { |
| if (g_selectedScene < int(g_scenes.size()) - 1) |
| g_selectedScene++; |
|
|
| |
| g_levelScroll = max((g_selectedScene - 4) * 24, 0); |
| break; |
| } |
| case SDLK_UP: |
| { |
| if (g_selectedScene > 0) |
| g_selectedScene--; |
|
|
| |
| g_levelScroll = max((g_selectedScene - 4) * 24, 0); |
| break; |
| } |
| case SDLK_LEFT: |
| { |
| if (g_scene > 0) |
| --g_scene; |
| Init(g_scene); |
|
|
| |
| g_levelScroll = max((g_scene - 4) * 24, 0); |
| break; |
| } |
| case SDLK_RIGHT: |
| { |
| if (g_scene < int(g_scenes.size()) - 1) |
| ++g_scene; |
| Init(g_scene); |
|
|
| |
| g_levelScroll = max((g_scene - 4) * 24, 0); |
| break; |
| } |
| } |
| } |
|
|
| void InputArrowKeysUp(int key, int x, int y) |
| { |
| } |
|
|
| bool InputKeyboardDown(unsigned char key, int x, int y) |
| { |
| if (key > '0' && key <= '9') |
| { |
| g_scene = key - '0' - 1; |
| Init(g_scene); |
| return false; |
| } |
|
|
| float kSpeed = g_camSpeed; |
|
|
| switch (key) |
| { |
| case 'w': |
| { |
| g_camVel.z = kSpeed; |
| break; |
| } |
| case 's': |
| { |
| g_camVel.z = -kSpeed; |
| break; |
| } |
| case 'a': |
| { |
| g_camVel.x = -kSpeed; |
| break; |
| } |
| case 'd': |
| { |
| g_camVel.x = kSpeed; |
| break; |
| } |
| case 'q': |
| { |
| g_camVel.y = kSpeed; |
| break; |
| } |
| case 'z': |
| { |
| |
| g_camVel.y = -kSpeed; |
| break; |
| } |
|
|
| case 'u': |
| { |
| #ifndef ANDROID |
| if (g_fullscreen) |
| { |
| SDL_SetWindowFullscreen(g_window, 0); |
| ReshapeWindow(1280, 720); |
| g_fullscreen = false; |
| } |
| else |
| { |
| SDL_SetWindowFullscreen(g_window, SDL_WINDOW_FULLSCREEN_DESKTOP); |
| g_fullscreen = true; |
| } |
| #endif |
| break; |
| } |
| case 'r': |
| { |
| g_resetScene = true; |
| break; |
| } |
| case 'y': |
| { |
| g_wavePool = !g_wavePool; |
| break; |
| } |
| case 'c': |
| { |
| #if _WIN32 |
| if (!g_ffmpeg) |
| { |
| |
|
|
| int i = 0; |
| char buf[255]; |
| FILE* f = NULL; |
|
|
| do |
| { |
| sprintf(buf, "../../movies/output%d.mp4", i); |
| f = fopen(buf, "rb"); |
| if (f) |
| fclose(f); |
|
|
| ++i; |
| } while (f); |
|
|
| const char* str = "ffmpeg -r 60 -f rawvideo -pix_fmt rgba -s 1280x720 -i - " |
| "-threads 0 -preset fast -y -crf 19 -pix_fmt yuv420p -tune animation -vf vflip %s"; |
|
|
| char cmd[1024]; |
| sprintf(cmd, str, buf); |
|
|
| g_ffmpeg = _popen(cmd, "wb"); |
| assert(g_ffmpeg); |
| } |
| else |
| { |
| _pclose(g_ffmpeg); |
| g_ffmpeg = NULL; |
| } |
|
|
| g_capture = !g_capture; |
| g_frame = 0; |
| #endif |
| break; |
| } |
| case 'p': |
| { |
| g_pause = !g_pause; |
| break; |
| } |
| case 'o': |
| { |
| g_step = true; |
| break; |
| } |
| case 'h': |
| { |
| g_showHelp = !g_showHelp; |
| break; |
| } |
| case 'e': |
| { |
| g_drawEllipsoids = !g_drawEllipsoids; |
| break; |
| } |
| case 't': |
| { |
| g_drawOpaque = !g_drawOpaque; |
| break; |
| } |
| case 'v': |
| { |
| g_drawPoints = !g_drawPoints; |
| break; |
| } |
| case 'f': |
| { |
| g_drawSprings = (g_drawSprings + 1) % 3; |
| break; |
| } |
| case 'i': |
| { |
| g_drawDiffuse = !g_drawDiffuse; |
| break; |
| } |
| case 'm': |
| { |
| g_drawMesh = !g_drawMesh; |
| break; |
| } |
| case 'n': |
| { |
| g_drawRopes = !g_drawRopes; |
| break; |
| } |
| case 'j': |
| { |
| g_windTime = 0.0f; |
| g_windStrength = 1.5f; |
| g_windFrequency = 0.2f; |
| break; |
| } |
| case '.': |
| { |
| g_profile = !g_profile; |
| break; |
| } |
| case 'g': |
| { |
| if (g_params.gravity[1] != 0.0f) |
| g_params.gravity[1] = 0.0f; |
| else |
| g_params.gravity[1] = -9.8f; |
|
|
| break; |
| } |
| case '-': |
| { |
| if (g_params.numPlanes) |
| g_params.numPlanes--; |
|
|
| break; |
| } |
| case ' ': |
| { |
| g_emit = !g_emit; |
| break; |
| } |
| case ';': |
| { |
| g_debug = !g_debug; |
| break; |
| } |
| case 13: |
| { |
| g_scene = g_selectedScene; |
| Init(g_scene); |
| break; |
| } |
| case 27: |
| { |
| |
| return true; |
| } |
| #if ENABLE_AFTERMATH_SUPPORT |
| case 'l': |
| DumpAftermathData(); |
| break; |
| #endif |
| }; |
|
|
| g_scenes[g_scene]->KeyDown(key); |
|
|
| return false; |
| } |
|
|
| void InputKeyboardUp(unsigned char key, int x, int y) |
| { |
| switch (key) |
| { |
| case 'w': |
| case 's': |
| { |
| g_camVel.z = 0.0f; |
| break; |
| } |
| case 'a': |
| case 'd': |
| { |
| g_camVel.x = 0.0f; |
| break; |
| } |
| case 'q': |
| case 'z': |
| { |
| g_camVel.y = 0.0f; |
| break; |
| } |
| }; |
| } |
|
|
| void MouseFunc(int b, int state, int x, int y) |
| { |
| switch (state) |
| { |
| case SDL_RELEASED: |
| { |
| g_lastx = x; |
| g_lasty = y; |
| g_lastb = -1; |
|
|
| break; |
| } |
| case SDL_PRESSED: |
| { |
| g_lastx = x; |
| g_lasty = y; |
| g_lastb = b; |
| #ifdef ANDROID |
| extern void setStateLeft(bool bLeftDown); |
| setStateLeft(false); |
| #else |
| if ((SDL_GetModState() & KMOD_LSHIFT) && g_lastb == SDL_BUTTON_LEFT) |
| { |
| |
| g_mousePicked = true; |
| } |
| #endif |
| break; |
| } |
| }; |
| } |
|
|
| void MousePassiveMotionFunc(int x, int y) |
| { |
| g_lastx = x; |
| g_lasty = y; |
| } |
|
|
| void MouseMotionFunc(unsigned state, int x, int y) |
| { |
| float dx = float(x - g_lastx); |
| float dy = float(y - g_lasty); |
|
|
| g_lastx = x; |
| g_lasty = y; |
|
|
| if (state & SDL_BUTTON_RMASK) |
| { |
| const float kSensitivity = DegToRad(0.1f); |
| const float kMaxDelta = FLT_MAX; |
|
|
| g_camAngle.x -= Clamp(dx*kSensitivity, -kMaxDelta, kMaxDelta); |
| g_camAngle.y -= Clamp(dy*kSensitivity, -kMaxDelta, kMaxDelta); |
| } |
| } |
|
|
| bool g_Error = false; |
|
|
| void ErrorCallback(NvFlexErrorSeverity severity, const char* msg, const char* file, int line) |
| { |
| printf("Flex: %s - %s:%d\n", msg, file, line); |
| g_Error = (severity == eNvFlexLogError); |
| |
| } |
|
|
| void ControllerButtonEvent(SDL_ControllerButtonEvent event) |
| { |
| |
| if (event.type == SDL_CONTROLLERBUTTONDOWN) |
| { |
| InputKeyboardDown(GetKeyFromGameControllerButton(SDL_GameControllerButton(event.button)), 0, 0); |
| InputArrowKeysDown(GetKeyFromGameControllerButton(SDL_GameControllerButton(event.button)), 0, 0); |
|
|
| if (event.button == SDL_CONTROLLER_BUTTON_LEFT_TRIGGER) |
| { |
| |
| g_lastx = g_screenWidth / 2; |
| g_lasty = g_screenHeight / 2; |
| g_lastb = 1; |
|
|
| |
| g_mousePicked = true; |
| } |
| } |
| else |
| { |
| InputKeyboardUp(GetKeyFromGameControllerButton(SDL_GameControllerButton(event.button)), 0, 0); |
| InputArrowKeysUp(GetKeyFromGameControllerButton(SDL_GameControllerButton(event.button)), 0, 0); |
|
|
| if (event.button == SDL_CONTROLLER_BUTTON_LEFT_TRIGGER) |
| { |
| |
| g_lastx = g_screenWidth / 2; |
| g_lasty = g_screenHeight / 2; |
| g_lastb = -1; |
| } |
| } |
| } |
|
|
| void ControllerDeviceUpdate() |
| { |
| if (SDL_NumJoysticks() > 0) |
| { |
| SDL_JoystickEventState(SDL_ENABLE); |
| if (SDL_IsGameController(0)) |
| { |
| g_gamecontroller = SDL_GameControllerOpen(0); |
| } |
| } |
| } |
|
|
| void SDLInit(const char* title) |
| { |
| if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0) |
| printf("Unable to initialize SDL"); |
|
|
| unsigned int flags = SDL_WINDOW_RESIZABLE; |
| #if !FLEX_DX |
| if (g_graphics == 0) |
| { |
| SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); |
| flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL; |
| } |
| #endif |
|
|
| g_window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, |
| g_screenWidth, g_screenHeight, flags); |
|
|
| g_windowId = SDL_GetWindowID(g_window); |
| } |
|
|
| void SDLMainLoop() |
| { |
| #if ENABLE_AFTERMATH_SUPPORT |
| __try |
| #endif |
| { |
| bool quit = false; |
| SDL_Event e; |
| while (!quit) |
| { |
| UpdateFrame(); |
|
|
| while (SDL_PollEvent(&e)) |
| { |
| switch (e.type) |
| { |
| case SDL_QUIT: |
| quit = true; |
| break; |
|
|
| case SDL_KEYDOWN: |
| if (e.key.keysym.sym < 256 && (e.key.keysym.mod == KMOD_NONE || (e.key.keysym.mod & KMOD_NUM))) |
| quit = InputKeyboardDown(e.key.keysym.sym, 0, 0); |
| InputArrowKeysDown(e.key.keysym.sym, 0, 0); |
| break; |
|
|
| case SDL_KEYUP: |
| if (e.key.keysym.sym < 256 && (e.key.keysym.mod == 0 || (e.key.keysym.mod & KMOD_NUM))) |
| InputKeyboardUp(e.key.keysym.sym, 0, 0); |
| InputArrowKeysUp(e.key.keysym.sym, 0, 0); |
| break; |
|
|
| case SDL_MOUSEMOTION: |
| if (e.motion.state) |
| MouseMotionFunc(e.motion.state, e.motion.x, e.motion.y); |
| else |
| MousePassiveMotionFunc(e.motion.x, e.motion.y); |
| break; |
|
|
| case SDL_MOUSEBUTTONDOWN: |
| case SDL_MOUSEBUTTONUP: |
| MouseFunc(e.button.button, e.button.state, e.motion.x, e.motion.y); |
| break; |
|
|
| case SDL_WINDOWEVENT: |
| if (e.window.windowID == g_windowId) |
| { |
| if (e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) |
| ReshapeWindow(e.window.data1, e.window.data2); |
| } |
| break; |
|
|
| case SDL_WINDOWEVENT_LEAVE: |
| g_camVel = Vec3(0.0f, 0.0f, 0.0f); |
| break; |
|
|
| case SDL_CONTROLLERBUTTONUP: |
| case SDL_CONTROLLERBUTTONDOWN: |
| ControllerButtonEvent(e.cbutton); |
| break; |
|
|
| case SDL_JOYDEVICEADDED: |
| case SDL_JOYDEVICEREMOVED: |
| ControllerDeviceUpdate(); |
| break; |
| } |
| } |
| } |
| } |
| #if ENABLE_AFTERMATH_SUPPORT |
| __except (true) |
| { |
| DumpAftermathData(); |
| } |
| #endif |
| } |
|
|
| int main(int argc, char* argv[]) |
| { |
| |
| for (int i = 1; i < argc; ++i) |
| { |
| int d; |
| if (sscanf(argv[i], "-device=%d", &d)) |
| g_device = d; |
|
|
| if (sscanf(argv[i], "-extensions=%d", &d)) |
| g_extensions = d != 0; |
|
|
| if (strcmp(argv[i], "-benchmark") == 0) |
| { |
| g_benchmark = true; |
| g_profile = true; |
| g_outputAllFrameTimes = false; |
| g_vsync = false; |
| g_fullscreen = true; |
| } |
|
|
| if (strcmp(argv[i], "-d3d12") == 0) |
| { |
| g_d3d12 = true; |
| |
| g_interop = false; |
| } |
|
|
| if (strcmp(argv[i], "-benchmarkAllFrameTimes") == 0) |
| { |
| g_benchmark = true; |
| g_outputAllFrameTimes = true; |
| } |
|
|
| if (strcmp(argv[i], "-tc") == 0) |
| { |
| g_teamCity = true; |
| } |
|
|
| if (sscanf(argv[i], "-msaa=%d", &d)) |
| g_msaaSamples = d; |
|
|
| int w = 1280; |
| int h = 720; |
| if (sscanf(argv[i], "-fullscreen=%dx%d", &w, &h) == 2) |
| { |
| g_screenWidth = w; |
| g_screenHeight = h; |
| g_fullscreen = true; |
| } |
| else if (strcmp(argv[i], "-fullscreen") == 0) |
| { |
| g_screenWidth = w; |
| g_screenHeight = h; |
| g_fullscreen = true; |
| } |
|
|
| if (sscanf(argv[i], "-windowed=%dx%d", &w, &h) == 2) |
| { |
| g_screenWidth = w; |
| g_screenHeight = h; |
| g_fullscreen = false; |
| } |
| else if (strstr(argv[i], "-windowed")) |
| { |
| g_screenWidth = w; |
| g_screenHeight = h; |
| g_fullscreen = false; |
| } |
|
|
| if (sscanf(argv[i], "-vsync=%d", &d)) |
| g_vsync = d != 0; |
|
|
| if (sscanf(argv[i], "-multiplier=%d", &d) == 1) |
| { |
| g_numExtraMultiplier = d; |
| } |
|
|
| if (strcmp(argv[i], "-disabletweak") == 0) |
| { |
| g_tweakPanel = false; |
| } |
|
|
| if (strcmp(argv[i], "-disableinterop") == 0) |
| { |
| g_interop = false; |
| } |
|
|
| if (sscanf(argv[i], "-asynccompute=%d", &d) == 1) |
| { |
| g_useAsyncCompute = (d != 0); |
| } |
|
|
| if (sscanf(argv[i], "-graphics=%d", &d) == 1) |
| { |
| if (d >= 0 && d <= 2) |
| g_graphics = d; |
| } |
| } |
|
|
| |
| g_scenes.push_back(new PotPourri("Pot Pourri")); |
|
|
| |
| SoftBody::Instance octopus("../../data/softs/octopus.obj"); |
| octopus.mScale = Vec3(32.0f); |
| octopus.mClusterSpacing = 2.75f; |
| octopus.mClusterRadius = 3.0f; |
| octopus.mClusterStiffness = 0.15f; |
| octopus.mSurfaceSampling = 1.0f; |
| SoftBody* softOctopusSceneNew = new SoftBody("Soft Octopus"); |
| softOctopusSceneNew->AddStack(octopus, 1, 3, 1); |
|
|
| SoftBody::Instance rope("../../data/rope.obj"); |
| rope.mScale = Vec3(50.0f); |
| rope.mClusterSpacing = 1.5f; |
| rope.mClusterRadius = 0.0f; |
| rope.mClusterStiffness = 0.55f; |
| SoftBody* softRopeSceneNew = new SoftBody("Soft Rope"); |
| softRopeSceneNew->AddInstance(rope); |
|
|
| SoftBody::Instance bowl("../../data/bowl_high.ply"); |
| bowl.mScale = Vec3(10.0f); |
| bowl.mClusterSpacing = 2.0f; |
| bowl.mClusterRadius = 2.0f; |
| bowl.mClusterStiffness = 0.55f; |
| SoftBody* softBowlSceneNew = new SoftBody("Soft Bowl"); |
| softBowlSceneNew->AddInstance(bowl); |
|
|
| SoftBody::Instance cloth("../../data/box_ultra_high.ply"); |
| cloth.mScale = Vec3(20.0f, 0.2f, 20.0f); |
| cloth.mClusterSpacing = 1.0f; |
| cloth.mClusterRadius = 2.0f; |
| cloth.mClusterStiffness = 0.2f; |
| cloth.mLinkRadius = 2.0f; |
| cloth.mLinkStiffness = 1.0f; |
| cloth.mSkinningFalloff = 1.0f; |
| cloth.mSkinningMaxDistance = 100.f; |
| SoftBody* softClothSceneNew = new SoftBody("Soft Cloth"); |
| softClothSceneNew->mRadius = 0.05f; |
| softClothSceneNew->AddInstance(cloth); |
|
|
| SoftBody::Instance rod("../../data/box_very_high.ply"); |
| rod.mScale = Vec3(20.0f, 2.0f, 2.0f); |
| rod.mTranslation = Vec3(-0.3f, 1.0f, 0.0f); |
| rod.mClusterSpacing = 2.0f; |
| rod.mClusterRadius = 2.0f; |
| rod.mClusterStiffness = 0.225f; |
| SoftBodyFixed* softRodSceneNew = new SoftBodyFixed("Soft Rod"); |
| softRodSceneNew->AddStack(rod, 3); |
|
|
| SoftBody::Instance teapot("../../data/teapot.ply"); |
| teapot.mScale = Vec3(25.0f); |
| teapot.mClusterSpacing = 3.0f; |
| teapot.mClusterRadius = 0.0f; |
| teapot.mClusterStiffness = 0.1f; |
| SoftBody* softTeapotSceneNew = new SoftBody("Soft Teapot"); |
| softTeapotSceneNew->AddInstance(teapot); |
|
|
| SoftBody::Instance armadillo("../../data/armadillo.ply"); |
| armadillo.mScale = Vec3(25.0f); |
| armadillo.mClusterSpacing = 3.0f; |
| armadillo.mClusterRadius = 0.0f; |
| SoftBody* softArmadilloSceneNew = new SoftBody("Soft Armadillo"); |
| softArmadilloSceneNew->AddInstance(armadillo); |
|
|
| SoftBody::Instance softbunny("../../data/bunny.ply"); |
| softbunny.mScale = Vec3(20.0f); |
| softbunny.mClusterSpacing = 3.5f; |
| softbunny.mClusterRadius = 0.0f; |
| softbunny.mClusterStiffness = 0.2f; |
| SoftBody* softBunnySceneNew = new SoftBody("Soft Bunny"); |
| softBunnySceneNew->AddInstance(softbunny); |
|
|
| |
| SoftBody::Instance plasticbunny("../../data/bunny.ply"); |
| plasticbunny.mScale = Vec3(10.0f); |
| plasticbunny.mClusterSpacing = 1.0f; |
| plasticbunny.mClusterRadius = 0.0f; |
| plasticbunny.mClusterStiffness = 0.0f; |
| plasticbunny.mGlobalStiffness = 1.0f; |
| plasticbunny.mClusterPlasticThreshold = 0.0015f; |
| plasticbunny.mClusterPlasticCreep = 0.15f; |
| plasticbunny.mTranslation[1] = 5.0f; |
| SoftBody* plasticBunniesSceneNew = new SoftBody("Plastic Bunnies"); |
| plasticBunniesSceneNew->mPlinth = true; |
| plasticBunniesSceneNew->AddStack(plasticbunny, 1, 10, 1, true); |
|
|
| SoftBody::Instance bunny1("../../data/bunny.ply"); |
| bunny1.mScale = Vec3(10.0f); |
| bunny1.mClusterSpacing = 1.0f; |
| bunny1.mClusterRadius = 0.0f; |
| bunny1.mClusterStiffness = 0.0f; |
| bunny1.mGlobalStiffness = 1.0f; |
| bunny1.mClusterPlasticThreshold = 0.0015f; |
| bunny1.mClusterPlasticCreep = 0.15f; |
| bunny1.mTranslation[1] = 5.0f; |
| SoftBody::Instance bunny2("../../data/bunny.ply"); |
| bunny2.mScale = Vec3(10.0f); |
| bunny2.mClusterSpacing = 1.0f; |
| bunny2.mClusterRadius = 0.0f; |
| bunny2.mClusterStiffness = 0.0f; |
| bunny2.mGlobalStiffness = 1.0f; |
| bunny2.mClusterPlasticThreshold = 0.0015f; |
| bunny2.mClusterPlasticCreep = 0.30f; |
| bunny2.mTranslation[1] = 5.0f; |
| bunny2.mTranslation[0] = 2.0f; |
| SoftBody* plasticComparisonScene = new SoftBody("Plastic Comparison"); |
| plasticComparisonScene->AddInstance(bunny1); |
| plasticComparisonScene->AddInstance(bunny2); |
| plasticComparisonScene->mPlinth = true; |
|
|
| SoftBody::Instance stackBox("../../data/box_high.ply"); |
| stackBox.mScale = Vec3(10.0f); |
| stackBox.mClusterSpacing = 1.5f; |
| stackBox.mClusterRadius = 0.0f; |
| stackBox.mClusterStiffness = 0.0f; |
| stackBox.mGlobalStiffness = 1.0f; |
| stackBox.mClusterPlasticThreshold = 0.0015f; |
| stackBox.mClusterPlasticCreep = 0.25f; |
| stackBox.mTranslation[1] = 1.0f; |
| SoftBody::Instance stackSphere("../../data/sphere.ply"); |
| stackSphere.mScale = Vec3(10.0f); |
| stackSphere.mClusterSpacing = 1.5f; |
| stackSphere.mClusterRadius = 0.0f; |
| stackSphere.mClusterStiffness = 0.0f; |
| stackSphere.mGlobalStiffness = 1.0f; |
| stackSphere.mClusterPlasticThreshold = 0.0015f; |
| stackSphere.mClusterPlasticCreep = 0.25f; |
| stackSphere.mTranslation[1] = 2.0f; |
| SoftBody* plasticStackScene = new SoftBody("Plastic Stack"); |
| plasticStackScene->AddInstance(stackBox); |
| plasticStackScene->AddInstance(stackSphere); |
| for (int i = 0; i < 3; i++) |
| { |
| stackBox.mTranslation[1] += 2.0f; |
| stackSphere.mTranslation[1] += 2.0f; |
| plasticStackScene->AddInstance(stackBox); |
| plasticStackScene->AddInstance(stackSphere); |
| } |
|
|
| g_scenes.push_back(softOctopusSceneNew); |
| g_scenes.push_back(softTeapotSceneNew); |
| g_scenes.push_back(softRopeSceneNew); |
| g_scenes.push_back(softClothSceneNew); |
| g_scenes.push_back(softBowlSceneNew); |
| g_scenes.push_back(softRodSceneNew); |
| g_scenes.push_back(softArmadilloSceneNew); |
| g_scenes.push_back(softBunnySceneNew); |
|
|
| g_scenes.push_back(plasticBunniesSceneNew); |
| g_scenes.push_back(plasticComparisonScene); |
| g_scenes.push_back(plasticStackScene); |
|
|
| |
| g_scenes.push_back(new FrictionRamp("Friction Ramp")); |
| g_scenes.push_back(new FrictionMovingShape("Friction Moving Box", 0)); |
| g_scenes.push_back(new FrictionMovingShape("Friction Moving Sphere", 1)); |
| g_scenes.push_back(new FrictionMovingShape("Friction Moving Capsule", 2)); |
| g_scenes.push_back(new FrictionMovingShape("Friction Moving Mesh", 3)); |
| g_scenes.push_back(new ShapeCollision("Shape Collision")); |
| g_scenes.push_back(new ShapeChannels("Shape Channels")); |
| g_scenes.push_back(new TriangleCollision("Triangle Collision")); |
| g_scenes.push_back(new LocalSpaceFluid("Local Space Fluid")); |
| g_scenes.push_back(new LocalSpaceCloth("Local Space Cloth")); |
| g_scenes.push_back(new CCDFluid("World Space Fluid")); |
|
|
| |
| g_scenes.push_back(new EnvironmentalCloth("Env Cloth Small", 6, 6, 40, 16)); |
| g_scenes.push_back(new EnvironmentalCloth("Env Cloth Large", 16, 32, 10, 3)); |
| g_scenes.push_back(new FlagCloth("Flag Cloth")); |
| g_scenes.push_back(new Inflatable("Inflatables")); |
| g_scenes.push_back(new ClothLayers("Cloth Layers")); |
| g_scenes.push_back(new SphereCloth("Sphere Cloth")); |
| g_scenes.push_back(new Tearing("Tearing")); |
| g_scenes.push_back(new Pasta("Pasta")); |
|
|
| |
| g_scenes.push_back(new GameMesh("Game Mesh Rigid", 0)); |
| g_scenes.push_back(new GameMesh("Game Mesh Particles", 1)); |
| g_scenes.push_back(new GameMesh("Game Mesh Fluid", 2)); |
| g_scenes.push_back(new GameMesh("Game Mesh Cloth", 3)); |
| g_scenes.push_back(new RigidDebris("Rigid Debris")); |
|
|
| |
| g_scenes.push_back(new Viscosity("Viscosity Low", 0.5f)); |
| g_scenes.push_back(new Viscosity("Viscosity Med", 3.0f)); |
| g_scenes.push_back(new Viscosity("Viscosity High", 5.0f, 0.12f)); |
| g_scenes.push_back(new Adhesion("Adhesion")); |
| g_scenes.push_back(new GooGun("Goo Gun", true)); |
|
|
| |
| g_scenes.push_back(new Buoyancy("Buoyancy")); |
| g_scenes.push_back(new Melting("Melting")); |
| g_scenes.push_back(new SurfaceTension("Surface Tension Low", 0.0f)); |
| g_scenes.push_back(new SurfaceTension("Surface Tension Med", 10.0f)); |
| g_scenes.push_back(new SurfaceTension("Surface Tension High", 20.0f)); |
| g_scenes.push_back(new DamBreak("DamBreak 5cm", 0.05f)); |
| g_scenes.push_back(new DamBreak("DamBreak 10cm", 0.1f)); |
| g_scenes.push_back(new DamBreak("DamBreak 15cm", 0.15f)); |
| g_scenes.push_back(new RockPool("Rock Pool")); |
| g_scenes.push_back(new RayleighTaylor2D("Rayleigh Taylor 2D")); |
|
|
| |
| g_scenes.push_back(new TriggerVolume("Trigger Volume")); |
| g_scenes.push_back(new ForceField("Force Field")); |
| g_scenes.push_back(new InitialOverlap("Initial Overlap")); |
|
|
| |
| g_scenes.push_back(new RigidPile("Rigid2", 2)); |
| g_scenes.push_back(new RigidPile("Rigid4", 4)); |
| g_scenes.push_back(new RigidPile("Rigid8", 12)); |
| g_scenes.push_back(new BananaPile("Bananas")); |
| g_scenes.push_back(new LowDimensionalShapes("Low Dimensional Shapes")); |
|
|
| |
| g_scenes.push_back(new GranularPile("Granular Pile")); |
|
|
| |
| g_scenes.push_back(new ParachutingBunnies("Parachuting Bunnies")); |
| g_scenes.push_back(new WaterBalloon("Water Balloons")); |
| g_scenes.push_back(new RigidFluidCoupling("Rigid Fluid Coupling")); |
| g_scenes.push_back(new FluidBlock("Fluid Block")); |
| g_scenes.push_back(new FluidClothCoupling("Fluid Cloth Coupling Water", false)); |
| g_scenes.push_back(new FluidClothCoupling("Fluid Cloth Coupling Goo", true)); |
| g_scenes.push_back(new BunnyBath("Bunny Bath Dam", true)); |
|
|
| |
| RenderInitOptions options; |
|
|
| #ifndef ANDROID |
| DemoContext* demoContext = nullptr; |
| #if FLEX_DX |
| |
| if (g_d3d12) |
| { |
| |
| |
| g_graphics = 2; |
| } |
| else |
| { |
| g_graphics = 1; |
| } |
| #else |
| switch (g_graphics) |
| { |
| case 0: break; |
| case 1: break; |
| case 2: |
| |
| |
| |
| g_interop = false; |
| break; |
| default: assert(0); |
| } |
| #endif |
| |
| CreateDemoContext(g_graphics); |
|
|
| std::string str; |
| #if FLEX_DX |
| if (g_d3d12) |
| str = "Flex Demo (Compute: DX12) "; |
| else |
| str = "Flex Demo (Compute: DX11) "; |
| #else |
| str = "Flex Demo (Compute: CUDA) "; |
| #endif |
| switch (g_graphics) |
| { |
| case 0: |
| str += "(Graphics: OpenGL)"; |
| break; |
| case 1: |
| str += "(Graphics: DX11)"; |
| break; |
| case 2: |
| str += "(Graphics: DX12)"; |
| break; |
| } |
| const char* title = str.c_str(); |
|
|
| SDLInit(title); |
|
|
| options.window = g_window; |
| options.numMsaaSamples = g_msaaSamples; |
| options.asyncComputeBenchmark = g_asyncComputeBenchmark; |
| options.defaultFontHeight = -1; |
| options.fullscreen = g_fullscreen; |
|
|
| InitRender(options); |
|
|
| if (g_fullscreen) |
| SDL_SetWindowFullscreen(g_window, SDL_WINDOW_FULLSCREEN_DESKTOP); |
|
|
| ReshapeWindow(g_screenWidth, g_screenHeight); |
|
|
| #endif |
|
|
| #if _WIN32 && !FLEX_DX |
| |
| if (g_device == -1) |
| g_device = NvFlexDeviceGetSuggestedOrdinal(); |
|
|
| |
| |
| |
| |
| bool success = NvFlexDeviceCreateCudaContext(g_device); |
|
|
| if (!success) |
| { |
| printf("Error creating CUDA context.\n"); |
| exit(-1); |
| } |
| #endif |
|
|
| NvFlexInitDesc desc; |
| desc.deviceIndex = g_device; |
| desc.enableExtensions = g_extensions; |
| desc.renderDevice = 0; |
| desc.renderContext = 0; |
| desc.computeContext = 0; |
| desc.computeType = eNvFlexCUDA; |
|
|
| #if FLEX_DX |
| if (g_d3d12) |
| desc.computeType = eNvFlexD3D12; |
| else |
| desc.computeType = eNvFlexD3D11; |
|
|
| bool userSpecifiedGpuToUseForFlex = (g_device != -1); |
|
|
| if (userSpecifiedGpuToUseForFlex) |
| { |
| |
| |
| |
| |
| g_interop = false; |
| } |
| else |
| { |
| |
| GetRenderDevice(&desc.renderDevice, |
| &desc.renderContext); |
| } |
|
|
| |
| |
| if (g_d3d12) |
| g_interop = false; |
|
|
| |
| |
| |
| |
| |
| |
| |
| desc.runOnRenderContext = false; |
| #else |
| |
| |
| if (g_d3d12) |
| g_interop = false; |
| #endif |
|
|
| |
| |
| g_flexLib = NvFlexInit(NV_FLEX_VERSION, ErrorCallback, &desc); |
|
|
| if (g_Error || g_flexLib == NULL) |
| { |
| printf("Could not initialize Flex, exiting.\n"); |
| exit(-1); |
| } |
|
|
| |
| strcpy(g_deviceName, NvFlexGetDeviceName(g_flexLib)); |
| printf("Compute Device: %s\n\n", g_deviceName); |
|
|
| if (g_benchmark) |
| g_scene = BenchmarkInit(); |
|
|
| |
| g_shadowMap = ShadowCreate(); |
|
|
| |
| StartGpuWork(); |
| Init(g_scene); |
| EndGpuWork(); |
|
|
| SDLMainLoop(); |
|
|
| if (g_fluidRenderer) |
| DestroyFluidRenderer(g_fluidRenderer); |
|
|
| DestroyFluidRenderBuffers(g_fluidRenderBuffers); |
| DestroyDiffuseRenderBuffers(g_diffuseRenderBuffers); |
|
|
| ShadowDestroy(g_shadowMap); |
|
|
| Shutdown(); |
| DestroyRender(); |
|
|
| SDL_DestroyWindow(g_window); |
| SDL_Quit(); |
|
|
| return 0; |
| } |
|
|