| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #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; |
| | } |
| |
|