aboutsummaryrefslogtreecommitdiff
path: root/demo/DemoApp/scene.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'demo/DemoApp/scene.cpp')
-rw-r--r--demo/DemoApp/scene.cpp1036
1 files changed, 1036 insertions, 0 deletions
diff --git a/demo/DemoApp/scene.cpp b/demo/DemoApp/scene.cpp
new file mode 100644
index 0000000..3ad7cce
--- /dev/null
+++ b/demo/DemoApp/scene.cpp
@@ -0,0 +1,1036 @@
+/*
+ * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, related documentation
+ * and any modifications thereto. Any use, reproduction, disclosure or
+ * distribution of this software and related documentation without an express
+ * license agreement from NVIDIA CORPORATION is strictly prohibited.
+ */
+
+#include "scene.h"
+
+#include <stdio.h>
+
+#include "loader.h"
+#include "imgui.h"
+#include "imguiser.h"
+
+#include "scene.h"
+
+#include <SDL.h>
+
+/// Scene registry here
+
+namespace Scenes
+{
+ SceneSimpleFlame sceneSimpleFlame;
+ SceneSimpleFlameThrower sceneSimpleFlameThrower;
+ SceneSimpleFlameAnimated sceneSimpleFlameAnimated;
+ Scene2DTextureEmitter scene2DTextureEmitter1(false);
+ Scene2DTextureEmitter scene2DTextureEmitter2(true);
+ SceneSimpleFlameMesh sceneSimpleFlameMesh;
+ SceneSimpleFlameCollision sceneSimpleFlameCollision;
+ //SceneSimpleFlameCulling sceneSimpleFlameCulling;
+ SceneSimpleFlameConvex sceneSimpleFlameConvex;
+ SceneSimpleFlameCapsule sceneSimpleFlameCapsule;
+ SceneSDFTest sceneSDFTest;
+ SceneCustomLighting sceneCustomLighting;
+ SceneSimpleSmoke sceneSimpleSmoke;
+ SceneDynamicCoupleRate sceneDynamicCoupleRate;
+ SceneCustomEmit sceneCustomEmit;
+ SceneSimpleFlameDouble sceneSimpleFlame2;
+ SceneSimpleFlameFuelMap sceneSimpleFlameFuelMap;
+ SceneSimpleFlameParticleSurface sceneParticleSurface;
+ SceneSimpleFlameBall sceneSimpleFlameBall;
+
+ const int count = 18;
+ Scene* list[count] = {
+ &scene2DTextureEmitter1,
+ &scene2DTextureEmitter2,
+ &sceneSimpleFlame,
+ &sceneSimpleFlameThrower,
+ &sceneSimpleFlameAnimated,
+ &sceneSimpleFlameMesh,
+ &sceneSDFTest,
+ &sceneSimpleFlameCollision,
+ //&sceneSimpleFlameCulling,
+ &sceneSimpleFlameConvex,
+ &sceneSimpleFlameCapsule,
+ &sceneSimpleSmoke,
+ &sceneCustomLighting,
+ &sceneDynamicCoupleRate,
+ &sceneCustomEmit,
+ &sceneSimpleFlame2,
+ &sceneSimpleFlameFuelMap,
+ &sceneParticleSurface,
+ &sceneSimpleFlameBall
+ };
+};
+
+Scene* getScene(int index)
+{
+ if (index < Scenes::count)
+ {
+ return Scenes::list[index];
+ }
+ return nullptr;
+}
+
+void pointsToImage(NvFlowFloat4* image, int imageDim, const CurvePoint* pts, int numPts)
+{
+ using namespace DirectX;
+ for (int i = 0; i < imageDim; i++)
+ {
+ float u = (float(i) + 0.5f) / float(imageDim);
+
+ // find the closest higher and lower control points
+ int xloweri = -1;
+ float xlowerVal = 0.f;
+ int xhigheri = -1;
+ float xhigherVal = 1.f;
+ for (int pt = 0; pt < numPts; pt++)
+ {
+ if (pts[pt].x <= u && pts[pt].x >= xlowerVal)
+ {
+ xloweri = pt;
+ xlowerVal = pts[pt].x;
+ }
+ if (pts[pt].x >= u && pts[pt].x <= xhigherVal)
+ {
+ xhigheri = pt;
+ xhigherVal = pts[pt].x;
+ }
+ }
+
+ // get values for interpolation
+ XMVECTOR a = (xloweri >= 0) ? XMLoadFloat4((XMFLOAT4*)&pts[xloweri].r) : XMVectorSet(0.f, 0.f, 0.f, 0.f);
+ XMVECTOR b = (xhigheri >= 0) ? XMLoadFloat4((XMFLOAT4*)&pts[xhigheri].r) : XMVectorSet(1.f, 1.f, 1.f, 1.f);
+ float t = (u - xlowerVal) / (xhigherVal - xlowerVal);
+ XMVECTOR c = XMVectorLerp(a, b, t);
+
+ XMStoreFloat4((XMFLOAT4*)&image[i], c);
+ }
+}
+
+void Scene::update(float dt)
+{
+ int numSteps = m_timeStepper.getNumSteps(dt);
+
+ for (int i = 0; i < numSteps; i++)
+ {
+ doUpdate(m_timeStepper.m_fixedDt);
+ }
+}
+
+void Scene::resize(int winw, int winh)
+{
+ m_winw = winw;
+ m_winh = winh;
+}
+
+bool Scene::imguiMouse(int mx, int my, unsigned char mbut)
+{
+ m_mx = mx;
+ m_my = my;
+ m_mbut = mbut;
+ return false;
+}
+
+// ************************* SceneFluid *****************************************
+
+void SceneFluid::imguiDesc()
+{
+ {
+ bool enableVTR = (m_flowGridActor.m_gridDesc.enableVTR != false);
+ if (imguiCheck("Enable VTR", enableVTR, true))
+ {
+ if (enableVTR == false)
+ {
+ NvFlowSupport support;
+ if (NvFlowGridQuerySupport(m_flowGridActor.m_grid, m_flowContext.m_gridContext, &support) == eNvFlowSuccess)
+ {
+ m_flowGridActor.m_gridDesc.enableVTR = support.supportsVTR;
+ }
+ }
+ else
+ {
+ m_flowGridActor.m_gridDesc.enableVTR = false;
+ }
+ m_shouldReset = true;
+ }
+ bool lowResDensity = m_flowGridActor.m_gridDesc.densityMultiRes == eNvFlowMultiRes1x1x1;
+ if (imguiCheck("Low Res Density", lowResDensity, true))
+ {
+ if (m_flowGridActor.m_gridDesc.densityMultiRes == eNvFlowMultiRes1x1x1)
+ {
+ m_flowGridActor.m_gridDesc.densityMultiRes = eNvFlowMultiRes2x2x2;
+ }
+ else
+ {
+ m_flowGridActor.m_gridDesc.densityMultiRes = eNvFlowMultiRes1x1x1;
+ }
+ m_shouldReset = true;
+ }
+ if (imguiCheck("Low Latency Mapping", m_flowGridActor.m_gridDesc.lowLatencyMapping, true))
+ {
+ m_flowGridActor.m_gridDesc.lowLatencyMapping = !m_flowGridActor.m_gridDesc.lowLatencyMapping;
+ m_shouldReset = true;
+ }
+ }
+ {
+ if (!m_flowContext.m_multiGPUSupported)
+ {
+ m_flowContext.m_enableMultiGPU = false;
+ }
+ if (imguiCheck("Enable MultiGPU", m_flowContext.m_enableMultiGPU, true))
+ {
+ m_flowContext.m_enableMultiGPU = !m_flowContext.m_enableMultiGPU;
+ if (!m_flowContext.m_multiGPUSupported)
+ {
+ m_flowContext.m_enableMultiGPU = false;
+ }
+ else
+ {
+ m_shouldReset = true;
+ }
+ }
+ }
+ {
+ if (!m_flowContext.m_commandQueueSupported)
+ {
+ m_flowContext.m_enableCommandQueue = false;
+ }
+ if (imguiCheck("Enable MultiQueue", m_flowContext.m_enableCommandQueue, true))
+ {
+ m_flowContext.m_enableCommandQueue = !m_flowContext.m_enableCommandQueue;
+ if (!m_flowContext.m_commandQueueSupported)
+ {
+ m_flowContext.m_enableCommandQueue = false;
+ }
+ else
+ {
+ m_shouldReset = true;
+ }
+ }
+ }
+
+ float oldMemoryLimit = m_flowGridActor.m_memoryLimit;
+ imguiserSlider("Memory Limit", &m_flowGridActor.m_memoryLimit, 1.f, 6.f, 1.f, true);
+ if (oldMemoryLimit != m_flowGridActor.m_memoryLimit)
+ {
+ m_flowGridActor.m_gridDesc.residentScale = m_flowGridActor.m_memoryLimit * m_flowGridActor.m_memoryScale;
+ m_shouldReset = true;
+ }
+
+ if (imguiButton("Reset", true))
+ {
+ m_shouldReset = true;
+ }
+
+ if (imguiButton("Grid Reset", true))
+ {
+ m_shouldGridReset = true;
+ }
+
+ float cellSizeLogf = float(m_flowGridActor.m_cellSizeLogScale);
+ if (imguiserSlider("Cell Size Log Scale", &cellSizeLogf, -6.f, 6.f, 1.f, true))
+ {
+ m_flowGridActor.m_cellSizeLogScale = int(cellSizeLogf);
+ m_shouldGridReset = true;
+ }
+ if (imguiserSlider("Cell Size Scale", &m_flowGridActor.m_cellSizeScale, 0.8f, 1.25f, 0.001f, true))
+ {
+ m_shouldGridReset = true;
+ }
+
+ imguiDescExtra();
+}
+
+void SceneFluid::imguiFluidSim()
+{
+ imguiSeparatorLine();
+ imguiLabel("Fluid Simulation");
+ imguiserBeginGroup("Fluid Simulation", nullptr);
+
+ imguiSeparator();
+ imguiLabel("Damping");
+ imguiserBeginGroup("Damping", nullptr);
+ imguiserSlider("Velocity", &m_flowGridActor.m_materialParams.velocity.damping, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Smoke", &m_flowGridActor.m_materialParams.smoke.damping, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Temp", &m_flowGridActor.m_materialParams.temperature.damping, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Fuel", &m_flowGridActor.m_materialParams.fuel.damping, 0.f, 1.f, 0.01f, true);
+ imguiserEndGroup();
+
+ imguiSeparator();
+ imguiLabel("Fade");
+ imguiserBeginGroup("Fade", nullptr);
+ imguiserSlider("Velocity", &m_flowGridActor.m_materialParams.velocity.fade, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Smoke", &m_flowGridActor.m_materialParams.smoke.fade, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Temp", &m_flowGridActor.m_materialParams.temperature.fade, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Fuel", &m_flowGridActor.m_materialParams.fuel.fade, 0.f, 1.f, 0.01f, true);
+ imguiserEndGroup();
+
+ imguiSeparator();
+ imguiLabel("MacCormack Correction");
+ imguiserBeginGroup("MacCormack Correction", nullptr);
+ imguiserSlider("Velocity", &m_flowGridActor.m_materialParams.velocity.macCormackBlendFactor, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Smoke", &m_flowGridActor.m_materialParams.smoke.macCormackBlendFactor, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Temp", &m_flowGridActor.m_materialParams.temperature.macCormackBlendFactor, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Fuel", &m_flowGridActor.m_materialParams.fuel.macCormackBlendFactor, 0.f, 1.f, 0.01f, true);
+ imguiserEndGroup();
+ imguiLabel("MacCormack Threshold");
+ imguiserBeginGroup("MacCormack Threshold", nullptr);
+ imguiserSlider("Velocity", &m_flowGridActor.m_materialParams.velocity.macCormackBlendThreshold, 0.f, 0.01f, 0.001f, true);
+ imguiserSlider("Smoke", &m_flowGridActor.m_materialParams.smoke.macCormackBlendThreshold, 0.f, 0.01f, 0.001f, true);
+ imguiserSlider("Temp", &m_flowGridActor.m_materialParams.temperature.macCormackBlendThreshold, 0.f, 0.01f, 0.001f, true);
+ imguiserSlider("Fuel", &m_flowGridActor.m_materialParams.fuel.macCormackBlendThreshold, 0.f, 0.01f, 0.001f, true);
+ imguiserEndGroup();
+
+ imguiserSlider("Vorticity Strength", &m_flowGridActor.m_materialParams.vorticityStrength, 0.f, 20.f, 0.1f, true);
+ imguiserSlider("Vorticity Vel Mask", &m_flowGridActor.m_materialParams.vorticityVelocityMask, 0.f, 1.f, 0.01f, true);
+
+ if (imguiCheck("Legacy Pressure", m_flowGridActor.m_gridParams.pressureLegacyMode, true))
+ {
+ m_flowGridActor.m_gridParams.pressureLegacyMode = !m_flowGridActor.m_gridParams.pressureLegacyMode;
+ }
+
+ imguiSeparator();
+ imguiLabel("Combustion");
+ imguiserBeginGroup("Combustion", nullptr);
+ imguiserSlider("Ignition Temp", &m_flowGridActor.m_materialParams.ignitionTemp, 0.f, 0.5f, 0.05f, true);
+ imguiserSlider("Cooling Rate", &m_flowGridActor.m_materialParams.coolingRate, 0.f, 10.f, 0.1f, true);
+ imguiserSlider("Buoyancy", &m_flowGridActor.m_materialParams.buoyancyPerTemp, 0.f, 10.f, 0.1f, true);
+ imguiserSlider("Expansion", &m_flowGridActor.m_materialParams.divergencePerBurn, 0.f, 10.f, 0.1f, true);
+ imguiserSlider("Smoke Per Burn", &m_flowGridActor.m_materialParams.smokePerBurn, 0.f, 10.f, 0.1f, true);
+ imguiserSlider("Temp Per Burn", &m_flowGridActor.m_materialParams.tempPerBurn, 0.f, 10.f, 0.1f, true);
+ imguiserSlider("Fuel Per Burn", &m_flowGridActor.m_materialParams.fuelPerBurn, 0.f, 10.f, 0.1f, true);
+ imguiserSlider("Burn Per Temp", &m_flowGridActor.m_materialParams.burnPerTemp, 0.f, 10.f, 0.1f, true);
+ imguiserEndGroup();
+
+ imguiFluidSimExtra();
+
+ imguiserEndGroup();
+}
+
+void SceneFluid::imguiFluidRender()
+{
+ imguiSeparatorLine();
+ imguiLabel("Rendering");
+ imguiserBeginGroup("Rendering", nullptr);
+ imguiserSlider("Alpha Scale", &m_flowGridActor.m_renderMaterialDefaultParams.alphaScale, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Additive", &m_flowGridActor.m_renderMaterialDefaultParams.additiveFactor, 0.f, 1.f, 0.01f, true);
+ float renderModef = (float)m_flowGridActor.m_renderParams.renderMode;
+ if (imguiserSlider("Render Mode", &renderModef, 0.f, float(eNvFlowVolumeRenderModeCount) - 1.f, 1.f, true))
+ {
+ m_flowGridActor.m_renderParams.renderMode = (NvFlowVolumeRenderMode)((NvFlowUint)renderModef);
+ }
+ float renderChannelf = (float)m_flowGridActor.m_renderParams.renderChannel;
+ if (imguiserSlider("Render Channel", &renderChannelf, 0.f, float(eNvFlowGridTextureChannelCount) - 1.f, 1.f, true))
+ {
+ m_flowGridActor.m_renderParams.renderChannel = (NvFlowGridTextureChannel)((NvFlowUint)renderChannelf);
+ }
+ if (imguiserCheck("Separate Lighting", m_flowGridActor.m_separateLighting, true))
+ {
+ m_flowGridActor.m_separateLighting = !m_flowGridActor.m_separateLighting;
+ }
+ if (imguiserCheck("Debug Render", m_flowGridActor.m_renderParams.debugMode, true))
+ {
+ m_flowGridActor.m_renderParams.debugMode = !m_flowGridActor.m_renderParams.debugMode;
+ }
+ if (m_flowGridActor.m_renderParams.debugMode)
+ {
+ imguiIndent();
+ if (imguiserCheck("Blocks", (m_flowGridActor.m_gridParams.debugVisFlags & eNvFlowGridDebugVisBlocks) != 0, true))
+ {
+ m_flowGridActor.m_gridParams.debugVisFlags = NvFlowGridDebugVisFlags(m_flowGridActor.m_gridParams.debugVisFlags ^ eNvFlowGridDebugVisBlocks);
+ }
+ if (imguiserCheck("Emit Bounds", (m_flowGridActor.m_gridParams.debugVisFlags & eNvFlowGridDebugVisEmitBounds) != 0, true))
+ {
+ m_flowGridActor.m_gridParams.debugVisFlags = NvFlowGridDebugVisFlags(m_flowGridActor.m_gridParams.debugVisFlags ^ eNvFlowGridDebugVisEmitBounds);
+ }
+ if (imguiserCheck("Shapes Simple", (m_flowGridActor.m_gridParams.debugVisFlags & eNvFlowGridDebugVisShapesSimple) != 0, true))
+ {
+ m_flowGridActor.m_gridParams.debugVisFlags = NvFlowGridDebugVisFlags(m_flowGridActor.m_gridParams.debugVisFlags ^ eNvFlowGridDebugVisShapesSimple);
+ }
+ imguiUnindent();
+ }
+ if (imguiserCheck("Edit ColorMap Default", m_flowGridActor.m_colorMap.m_curveEditorActiveDefault, true))
+ {
+ m_flowGridActor.m_colorMap.m_curveEditorActiveDefault = !m_flowGridActor.m_colorMap.m_curveEditorActiveDefault;
+ }
+ if (imguiserCheck("Edit ColorMap Mat0", m_flowGridActor.m_colorMap.m_curveEditorActiveMat0, true))
+ {
+ m_flowGridActor.m_colorMap.m_curveEditorActiveMat0 = !m_flowGridActor.m_colorMap.m_curveEditorActiveMat0;
+ }
+ if (imguiserCheck("Edit ColorMap Mat1", m_flowGridActor.m_colorMap.m_curveEditorActiveMat1, true))
+ {
+ m_flowGridActor.m_colorMap.m_curveEditorActiveMat1 = !m_flowGridActor.m_colorMap.m_curveEditorActiveMat1;
+ }
+ if (imguiserCheck("Multires", m_flowGridActor.m_renderParams.multiRes.enabled, true))
+ {
+ m_flowGridActor.m_renderParams.multiRes.enabled = !m_flowGridActor.m_renderParams.multiRes.enabled;
+ }
+ if (imguiserCheck("Lens Matched", m_flowGridActor.m_renderParams.lensMatchedShading.enabled, true))
+ {
+ m_flowGridActor.m_renderParams.lensMatchedShading.enabled = !m_flowGridActor.m_renderParams.lensMatchedShading.enabled;
+ }
+ if (m_flowGridActor.m_renderParams.multiRes.enabled)
+ {
+ m_flowGridActor.m_renderParams.multiRes.viewport.width = (float)m_winw;
+ m_flowGridActor.m_renderParams.multiRes.viewport.height = (float)m_winh;
+ m_flowGridActor.m_renderParams.multiRes.nonMultiResWidth = (float)m_winw;
+ m_flowGridActor.m_renderParams.multiRes.nonMultiResHeight = (float)m_winh;
+ }
+ if (m_flowGridActor.m_renderParams.lensMatchedShading.enabled)
+ {
+ m_flowGridActor.m_renderParams.lensMatchedShading.viewport.width = (float)m_winw;
+ m_flowGridActor.m_renderParams.lensMatchedShading.viewport.height = (float)m_winh;
+ m_flowGridActor.m_renderParams.lensMatchedShading.nonLMSWidth = (float)m_winw;
+ m_flowGridActor.m_renderParams.lensMatchedShading.nonLMSHeight = (float)m_winh;
+ }
+ imguiserSlider("Screen Percentage", &m_flowGridActor.m_renderParams.screenPercentage, 0.1f, 1.f, 0.01f, true);
+ float smoothVal = float(m_flowGridActor.m_renderParams.smoothColorUpsample);
+ if (imguiserSlider("Upsample Smooth", &smoothVal, 0.f, 1.f, 1.f, true))
+ {
+ m_flowGridActor.m_renderParams.smoothColorUpsample = smoothVal > 0.5f;
+ }
+ if (imguiserCheck("Generate Depth", m_flowGridActor.m_renderParams.generateDepth, true))
+ {
+ m_flowGridActor.m_renderParams.generateDepth = !m_flowGridActor.m_renderParams.generateDepth;
+ }
+ if (imguiserCheck("Generate Depth Vis", m_flowGridActor.m_renderParams.generateDepthDebugMode, true))
+ {
+ m_flowGridActor.m_renderParams.generateDepthDebugMode = !m_flowGridActor.m_renderParams.generateDepthDebugMode;
+ }
+
+ imguiLabel("MultiRes Ray March");
+ float multiResRayMarchf = (float)m_flowGridActor.m_renderParams.multiResRayMarch;
+ if (imguiserSlider("MultiRes levels", &multiResRayMarchf, 0.f, 4.f, 1.f, true))
+ {
+ m_flowGridActor.m_renderParams.multiResRayMarch = (NvFlowMultiResRayMarch)NvFlowUint(multiResRayMarchf);
+ }
+ imguiserSlider("Sampling Rate", &m_flowGridActor.m_renderParams.multiResSamplingScale, 0.1f, 10.f, 0.1f, true);
+
+ imguiLabel("Volume Shadow");
+ if (imguiserCheck("Enabled", m_flowGridActor.m_enableVolumeShadow, true))
+ {
+ m_flowGridActor.m_enableVolumeShadow = !m_flowGridActor.m_enableVolumeShadow;
+ m_shouldReset = true;
+ }
+ if (m_flowGridActor.m_enableVolumeShadow)
+ {
+ if (imguiserCheck("Force Apply", m_flowGridActor.m_forceApplyShadow, true))
+ {
+ m_flowGridActor.m_forceApplyShadow = !m_flowGridActor.m_forceApplyShadow;
+ }
+ imguiserSlider("Light Pan", &m_flowGridActor.m_shadowPan, -4.f, 4.f, 0.01f, true);
+ imguiserSlider("Light Tilt", &m_flowGridActor.m_shadowTilt, -4.f, 4.f, 0.01f, true);
+ if (imguiserSlider("Memory Scale", &m_flowGridActor.m_shadowResidentScale, 0.5f, 2.f, 0.1f, true))
+ {
+ m_shouldReset = true;
+ }
+ imguiserSlider("Intensity Scale", &m_flowGridActor.m_shadowIntensityScale, 0.f, 5.f, 0.01f, true);
+ imguiserSlider("Min Intensity", &m_flowGridActor.m_shadowMinIntensity, 0.0f, 1.f, 0.01f, true);
+ imguiserSlider("BlendTempFactor", &m_flowGridActor.m_shadowBlendCompMask.x, -5.f, 5.f, 0.1f, true);
+ imguiserSlider("BlendBias", &m_flowGridActor.m_shadowBlendBias, -5.0f, 5.f, 0.1f, true);
+ if (imguiserCheck("Debug Vis", m_flowGridActor.m_shadowDebugVis, true))
+ {
+ m_flowGridActor.m_shadowDebugVis = !m_flowGridActor.m_shadowDebugVis;
+ }
+ }
+
+ imguiLabel("Cross Section");
+ if (imguiserCheck("Enabled", m_flowGridActor.m_enableCrossSection, true))
+ {
+ m_flowGridActor.m_enableCrossSection = !m_flowGridActor.m_enableCrossSection;
+ }
+ if (m_flowGridActor.m_enableCrossSection)
+ {
+ if (imguiserCheck("Fullscreen", m_flowGridActor.m_crossSectionParams.fullscreen, true))
+ {
+ m_flowGridActor.m_crossSectionParams.fullscreen = !m_flowGridActor.m_crossSectionParams.fullscreen;
+ }
+ if (imguiserCheck("Point Filter", m_flowGridActor.m_crossSectionParams.pointFilter, true))
+ {
+ m_flowGridActor.m_crossSectionParams.pointFilter = !m_flowGridActor.m_crossSectionParams.pointFilter;
+ }
+ if (imguiserCheck("Velocity Vectors", m_flowGridActor.m_crossSectionParams.velocityVectors, true))
+ {
+ m_flowGridActor.m_crossSectionParams.velocityVectors = !m_flowGridActor.m_crossSectionParams.velocityVectors;
+ }
+ if (imguiserCheck("Outline Cells", m_flowGridActor.m_crossSectionParams.outlineCells, true))
+ {
+ m_flowGridActor.m_crossSectionParams.outlineCells = !m_flowGridActor.m_crossSectionParams.outlineCells;
+ }
+
+ float axis = float(m_flowGridActor.m_crossSectionParams.crossSectionAxis);
+ if (imguiserSlider("Axis", &axis, 0.f, 2.f, 1.f, true))
+ {
+ m_flowGridActor.m_crossSectionParams.crossSectionAxis = NvFlowUint(axis);
+ }
+ imguiserSlider("PosX", &m_flowGridActor.m_crossSectionParams.crossSectionPosition.x, -1.f, 1.f, 0.01f, true);
+ imguiserSlider("PosY", &m_flowGridActor.m_crossSectionParams.crossSectionPosition.y, -1.f, 1.f, 0.01f, true);
+ imguiserSlider("PosZ", &m_flowGridActor.m_crossSectionParams.crossSectionPosition.z, -1.f, 1.f, 0.01f, true);
+ imguiserSlider("Scale", &m_flowGridActor.m_crossSectionScale, 0.25f, 20.f, 0.1f, true);
+
+ float renderModef = (float)m_flowGridActor.m_crossSectionParams.renderMode;
+ if (imguiserSlider("Cross Render Mode", &renderModef, 0.f, float(eNvFlowVolumeRenderModeCount) - 1.f, 1.f, true))
+ {
+ m_flowGridActor.m_crossSectionParams.renderMode = (NvFlowVolumeRenderMode)((NvFlowUint)renderModef);
+ }
+ float renderChannelf = (float)m_flowGridActor.m_crossSectionParams.renderChannel;
+ if (imguiserSlider("Cross Render Channel", &renderChannelf, 0.f, float(eNvFlowGridTextureChannelCount) - 1.f, 1.f, true))
+ {
+ m_flowGridActor.m_crossSectionParams.renderChannel = (NvFlowGridTextureChannel)((NvFlowUint)renderChannelf);
+ }
+ imguiserSlider("Intensity", &m_flowGridActor.m_crossSectionParams.intensityScale, 0.01f, 10.f, 0.01f, true);
+ imguiserSlider("Background Color", &m_flowGridActor.m_crossSectionBackgroundColor, 0.f, 1.f, 1.f, true);
+ imguiserSlider("Line Color R", &m_flowGridActor.m_crossSectionLineColor.x, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Line Color G", &m_flowGridActor.m_crossSectionLineColor.y, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Line Color B", &m_flowGridActor.m_crossSectionLineColor.z, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Cell Color R", &m_flowGridActor.m_crossSectionParams.cellColor.x, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Cell Color G", &m_flowGridActor.m_crossSectionParams.cellColor.y, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Cell Color B", &m_flowGridActor.m_crossSectionParams.cellColor.z, 0.f, 1.f, 0.01f, true);
+
+ imguiserSlider("Velocity Scale", &m_flowGridActor.m_crossSectionParams.velocityScale, 0.1f, 10.f, 0.01f, true);
+ imguiserSlider("Vector Length", &m_flowGridActor.m_crossSectionParams.vectorLengthScale, 0.1f, 2.f, 0.01f, true);
+ }
+
+ imguiFluidRenderExtra();
+ imguiserEndGroup();
+}
+
+void SceneFluid::imguiFluidEmitter()
+{
+ imguiSeparatorLine();
+ imguiLabel("Emitter");
+ imguiserBeginGroup("Emitter", nullptr);
+ imguiserSlider("Emit Velocity", &m_emitParams.velocityLinear.y, -16.f, 16.f, 0.1f, true);
+ imguiserSlider("Emit Smoke", &m_emitParams.smoke, 0.f, 10.f, 0.1f, true);
+ imguiserSlider("Emit Temp", &m_emitParams.temperature, 0.f, 10.f, 0.1f, true);
+ imguiserSlider("Emit Fuel", &m_emitParams.fuel, 0.f, 10.f, 0.1f, true);
+ imguiserSlider("Max Emit Dist", &m_emitParams.maxActiveDist, -1.f, 1.f, 0.01f, true);
+ imguiserSlider("Min Emit Dist", &m_emitParams.minActiveDist, -1.f, 1.f, 0.01f, true);
+ imguiserSlider("Max Edge Dist", &m_emitParams.maxEdgeDist, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Min Edge Dist", &m_emitParams.minEdgeDist, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Fuel Release Temp", &m_emitParams.fuelReleaseTemp, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Fuel Release", &m_emitParams.fuelRelease, 0.f, 10.f, 0.1f, true);
+ //imguiserSlider("Slip Thickness", &m_emitParams.slipThickness, 0.f, 1.f, 0.01f, true);
+ //imguiserSlider("Slip Factor", &m_emitParams.slipFactor, 0.f, 1.f, 0.01f, true);
+ float allocScale = m_emitParams.allocationScale.x;
+ if (imguiserSlider("Alloc Scale", &allocScale, 0.f, 2.f, 0.01f, true))
+ {
+ m_emitParams.allocationScale = { allocScale, allocScale, allocScale };
+ }
+ imguiserSlider("Alloc Predict", &m_emitParams.allocationPredict, 0.f, 1.f, 0.01f, true);
+ imguiFluidEmitterExtra();
+ imguiserEndGroup();
+}
+
+void SceneFluid::imguiFluidAlloc()
+{
+ imguiSeparatorLine();
+ imguiLabel("Fluid Allocation");
+ imguiserBeginGroup("Fluid Allocation", nullptr);
+
+ if (imguiserCheck("Big Effect Mode", m_flowGridActor.m_gridParams.bigEffectMode, true))
+ {
+ m_flowGridActor.m_gridParams.bigEffectMode = !m_flowGridActor.m_gridParams.bigEffectMode;
+ }
+ imguiserSlider("Predict Time", &m_flowGridActor.m_gridParams.bigEffectPredictTime, 0.f, 1.f, 0.01f, true);
+
+ imguiserSlider("Velocity Weight", &m_flowGridActor.m_materialParams.velocity.allocWeight, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Smoke Weight", &m_flowGridActor.m_materialParams.smoke.allocWeight, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Temp Weight", &m_flowGridActor.m_materialParams.temperature.allocWeight, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Fuel Weight", &m_flowGridActor.m_materialParams.fuel.allocWeight, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Velocity Threshold", &m_flowGridActor.m_materialParams.velocity.allocThreshold, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Smoke Threshold", &m_flowGridActor.m_materialParams.smoke.allocThreshold, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Temp Threshold", &m_flowGridActor.m_materialParams.temperature.allocThreshold, 0.f, 1.f, 0.01f, true);
+ imguiserSlider("Fuel Threshold", &m_flowGridActor.m_materialParams.fuel.allocThreshold, 0.f, 1.f, 0.01f, true);
+
+ imguiFluidAllocExtra();
+ imguiserEndGroup();
+}
+
+void SceneFluid::imguiFluidTime()
+{
+ imguiSeparatorLine();
+ imguiLabel("Simulation Update Time");
+ {
+ NvFlowQueryTime timeGPU, timeCPU;
+ if (NvFlowGridQueryTime(m_flowGridActor.m_grid, &timeGPU, &timeCPU) == eNvFlowSuccess)
+ {
+ char buf[80];
+ snprintf(buf, sizeof(buf), "GPU: %.3f ms", 1000.f * timeGPU.simulation);
+ imguiValue(buf);
+ snprintf(buf, sizeof(buf), "CPU: %.3f ms", 1000.f * timeCPU.simulation);
+ imguiValue(buf);
+ }
+ }
+ imguiFluidTimeExtra();
+}
+
+void SceneFluid::imguiLoadSave()
+{
+ imguiSeparatorLine();
+
+ static float saveSlot = 0.f;
+ imguiSlider("Save Slot", &saveSlot, 0.f, 7.f, 1.f, true);
+
+ char buf[256u];
+ snprintf(buf, 256u, "../../data/save%d.h", int(saveSlot));
+
+ if (imguiButton("Save"))
+ {
+ imguiserSave(buf);
+ }
+
+ if (imguiButton("Load"))
+ {
+ imguiserLoad(buf);
+ }
+}
+
+void SceneFluid::imgui(int xIn, int yIn, int wIn, int hIn)
+{
+ static int scroll = 0u;
+
+ int border = xIn;
+ int x = xIn;
+ int y = border;
+ int w = wIn;
+ int h = m_winh - (hIn + border) - 2 * border;
+ m_editorWidth = x + w;
+
+ imguiBeginScrollArea("Options",
+ x, y,
+ w, h,
+ &scroll);
+
+ imguiserBeginGroup("Effect", nullptr);
+
+ imguiDesc();
+
+ imguiSeparatorLine();
+
+ m_projectile.imgui();
+
+ imguiFluidSim();
+
+ imguiFluidEmitter();
+
+ imguiFluidRender();
+
+ imguiFluidAlloc();
+
+ imguiLoadSave();
+
+ imguiFluidTime();
+
+ imguiEndScrollArea();
+
+ m_flowGridActor.m_colorMap.imguiUpdate(this, m_flowContext.m_renderContext, border, x, y, w, h);
+
+ imguiserEndGroup();
+}
+
+bool SceneFluid::imguiMouse(int mx, int my, unsigned char mbut)
+{
+ Scene::imguiMouse(mx, my, mbut);
+
+ if (mx < m_editorWidth) return true;
+
+ if (m_flowGridActor.m_colorMap.colorMapActive(mx, my, mbut)) return true;
+
+ return false;
+}
+
+void SceneFluid::reset()
+{
+ release();
+ SDL_Delay(30);
+ init(m_appctx, m_winw, m_winh);
+ m_shouldReset = false;
+}
+
+NvFlowUint64 SceneFluid::getGridGPUMemUsage()
+{
+ NvFlowUint64 totalBytes = 0u;
+
+ if (m_flowGridActor.m_grid)
+ {
+ NvFlowGridGPUMemUsage(m_flowGridActor.m_grid, &totalBytes);
+ }
+
+ return totalBytes;
+}
+
+bool SceneFluid::getStats(int lineIdx, int statIdx, char* buf)
+{
+ switch (statIdx)
+ {
+ case 0:
+ {
+ NvFlowUint64 totalBytes = getGridGPUMemUsage();
+ snprintf(buf, 79, "GridGPUMem: %llu bytes", totalBytes);
+ return true;
+ }
+ case 1:
+ {
+ NvFlowUint numLayers = m_flowGridActor.m_statNumLayers;
+ snprintf(buf, 79, "NumLayers: %d layers", numLayers);
+ return true;
+ }
+ case 2:
+ {
+ NvFlowUint numBlocks = m_flowGridActor.m_statNumDensityBlocks;
+ NvFlowUint maxBlocks = m_flowGridActor.m_statMaxDensityBlocks;
+ snprintf(buf, 79, "Density: %d blocks active of %d", numBlocks, maxBlocks);
+ return true;
+ }
+ case 3:
+ {
+ NvFlowUint numBlocks = m_flowGridActor.m_statNumVelocityBlocks;
+ NvFlowUint maxBlocks = m_flowGridActor.m_statMaxVelocityBlocks;
+ snprintf(buf, 79, "Velocity: %d blocks active of %d", numBlocks, maxBlocks);
+ return true;
+ }
+ case 4:
+ {
+ NvFlowUint numCells = m_flowGridActor.m_statNumDensityCells;
+ snprintf(buf, 79, "Density: %d cells active", numCells);
+ return true;
+ }
+ case 5:
+ {
+ NvFlowUint numCells = m_flowGridActor.m_statNumVelocityCells;
+ snprintf(buf, 79, "Velocity: %d cells active", numCells);
+ return true;
+ }
+ case 6:
+ {
+ if (m_flowGridActor.m_statVolumeShadowBlocks > 0u)
+ {
+ NvFlowUint numBlocks = m_flowGridActor.m_statVolumeShadowBlocks;
+ snprintf(buf, 79, "Shadow: %d blocks active", numBlocks);
+ return true;
+ }
+ return false;
+ }
+ case 7:
+ {
+ if (m_flowGridActor.m_statVolumeShadowCells > 0u)
+ {
+ NvFlowUint numCells = m_flowGridActor.m_statVolumeShadowCells;
+ snprintf(buf, 79, "Shadow: %d cells active", numCells);
+ return true;
+ }
+ return false;
+ }
+ default:
+ {
+ return false;
+ }
+ }
+}
+
+// ***************************** Projectile ********************************
+
+void Projectile::init(AppGraphCtx* appctx, NvFlowContext* context)
+{
+ NvFlowGridEmitParamsDefaults(&m_emitParams);
+ m_emitParams.bounds.x.x = m_radius;
+ m_emitParams.bounds.y.y = m_radius;
+ m_emitParams.bounds.z.z = m_radius;
+ m_emitParams.bounds.w.y = 0.f;
+
+ m_emitParams.velocityCoupleRate = { 10.f, 10.f, 10.f };
+
+ m_emitParams.temperature = 0.f;
+ m_emitParams.temperatureCoupleRate = 10.f;
+
+ m_emitParams.fuel = 0.f;
+ m_emitParams.fuelCoupleRate = 10.f;
+
+ m_emitParams.smoke = 0.f;
+ m_emitParams.smokeCoupleRate = 10.f;
+
+ m_emitParams.allocationScale = { 0.f, 0.f, 0.f };
+
+ updateEmitterMode();
+
+ m_appctx = appctx;
+ m_meshContext = MeshInteropContextCreate(appctx);
+ m_mesh = MeshCreate(m_meshContext);
+
+ MeshLoadFromFile(m_mesh, "../../data/sphere_high.ply");
+
+ NvFlowShapeSDFDesc shapeDesc;
+ NvFlowShapeSDFDescDefaults(&shapeDesc);
+ shapeDesc.resolution = { 32u, 32u, 32u };
+ m_shape = NvFlowCreateShapeSDF(context, &shapeDesc);
+
+ // generate sphere SDF
+ const float radius = 0.8f;
+ auto mappedData = NvFlowShapeSDFMap(m_shape, context);
+ if (mappedData.data)
+ {
+ for (NvFlowUint k = 0; k < mappedData.dim.z; k++)
+ for (NvFlowUint j = 0; j < mappedData.dim.y; j++)
+ for (NvFlowUint i = 0; i < mappedData.dim.x; i++)
+ {
+ float& val = mappedData.data[k * mappedData.depthPitch + j * mappedData.rowPitch + i];
+
+ float x = 2.f * (float(i) + 0.5f) / float(mappedData.dim.x) - 1.f;
+ float y = 2.f * (float(j) + 0.5f) / float(mappedData.dim.y) - 1.f;
+ float z = 2.f * (float(k) + 0.5f) / float(mappedData.dim.z) - 1.f;
+
+ float d = sqrtf(x*x + y*y + z*z);
+ float v = d - radius;
+
+ val = v;
+ }
+ NvFlowShapeSDFUnmap(m_shape, context);
+ }
+}
+
+void Projectile::updatePosition(Path& path, float dt)
+{
+ if (path.m_active)
+ {
+ path.m_time -= dt;
+ if (path.m_time > path.m_timeEnd)
+ {
+ float wx = path.m_direction[0];
+ float wy = path.m_direction[1];
+ float wz = path.m_direction[2];
+
+ m_emitParams.smoke = 0.f;
+ m_emitParams.temperature = m_temperature;
+ m_emitParams.fuel = m_fuel;
+ m_emitParams.velocityLinear.x = -m_speed * wx;
+ m_emitParams.velocityLinear.y = -m_speed * wy;
+ m_emitParams.velocityLinear.z = -m_speed * wz;
+ float dist = m_speed * path.m_time;
+ path.m_position[0] = dist * wx + path.m_offset[0];
+ path.m_position[1] = dist * wy + path.m_offset[1];
+ path.m_position[2] = dist * wz + path.m_offset[2];
+ m_emitParams.bounds.w.x = path.m_position[0];
+ m_emitParams.bounds.w.y = path.m_position[1];
+ m_emitParams.bounds.w.z = path.m_position[2];
+ }
+ else
+ {
+ path.m_time = path.m_timeEnd;
+ path.m_active = false;
+ }
+ }
+}
+
+void Projectile::update(NvFlowContext* context, NvFlowGrid* grid, float dt)
+{
+ int maxActive = -1;
+ for (int i = 0; i < m_pathsSize; i++)
+ {
+ Path& path = m_paths[i];
+ if (path.m_active)
+ {
+ maxActive = i;
+ const int numSubSteps = 4;
+ const float convert = 3.14159f / 180.f;
+ float stepdt = dt / float(numSubSteps);
+ for (int i = 0; i < numSubSteps; i++)
+ {
+ updatePosition(path, stepdt);
+
+ NvFlowShapeDesc shapeDesc;
+ shapeDesc.sphere.radius = 0.8f;
+
+ m_emitParams.localToWorld = m_emitParams.bounds;
+ m_emitParams.shapeType = eNvFlowShapeTypeSphere;
+ m_emitParams.deltaTime = stepdt;
+
+ NvFlowGridEmit(grid, &shapeDesc, 1u, &m_emitParams, 1u);
+ }
+ }
+ }
+ m_pathsSize = maxActive + 1;
+}
+
+void Projectile::draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view)
+{
+ m_view = view;
+ m_projection = projection;
+
+ MeshInteropContextUpdate(m_meshContext, m_appctx);
+
+ if (m_shouldDrawMesh)
+ {
+ for (int i = 0; i < m_pathsSize; i++)
+ {
+ Path& path = m_paths[i];
+ if (path.m_active)
+ {
+ MeshDrawParams meshDrawParams;
+ meshDrawParams.renderMode = MESH_RENDER_SOLID;
+ meshDrawParams.projection = projection;
+ meshDrawParams.view = view;
+ meshDrawParams.model = DirectX::XMMatrixMultiply(
+ DirectX::XMMatrixScaling(0.8f * m_radius, 0.8f * m_radius, 0.8f * m_radius),
+ DirectX::XMMatrixTranslation(path.m_position[0], path.m_position[1], path.m_position[2])
+ );
+
+ MeshDraw(m_mesh, &meshDrawParams);
+ }
+ }
+ }
+}
+
+void Projectile::shoot()
+{
+ // find open path
+ int allocIdx = 0;
+ bool allocSuccess = false;
+ for (; allocIdx < m_pathsCap; allocIdx++)
+ {
+ Path& path = m_paths[allocIdx];
+ if (!path.m_active)
+ {
+ allocSuccess = true;
+ break;
+ }
+ }
+ if (allocSuccess)
+ {
+ // update size
+ if (allocIdx + 1 > m_pathsSize)
+ {
+ m_pathsSize = allocIdx + 1;
+ }
+ // create path reference
+ Path& path = m_paths[allocIdx];
+ path.m_active = true;
+ // compute direction
+ {
+ using namespace DirectX;
+ // compute eye direction
+ XMVECTOR screenDir = XMVectorSet(1.f, 0.f, 0.f, 0.f);
+ XMMATRIX viewInv = XMMatrixInverse(nullptr, m_view);
+ XMVECTOR worldDir = XMVector4Transform(screenDir, viewInv);
+ worldDir = XMVector3Normalize(worldDir);
+
+ XMMATRIX viewProj = XMMatrixMultiply(m_view, m_projection);
+ XMMATRIX viewProjInv = XMMatrixInverse(nullptr, viewProj);
+
+ float txp = 0.f;
+ float txn = 0.f;
+ {
+ XMVECTOR pos = XMVectorSet(0.f, 0.f, 0.f, 1.f);
+ XMVECTOR screencenter = XMVector4Transform(pos, viewProj);
+ screencenter = screencenter / XMVectorSplatW(screencenter);
+
+ pos = worldDir + XMVectorSet(0.f, 0.f, 0.f, 1.f);
+ XMVECTOR screenpos = XMVector4Transform(pos, viewProj);
+ screenpos = screenpos / XMVectorSplatW(screenpos);
+
+ // compute world offset
+ XMVECTOR offset = XMVectorSet(1.f, 0.f, 1.f, 1.f) * screencenter;
+ offset = XMVector4Transform(offset, viewProjInv);
+ offset = offset / XMVectorSplatW(offset);
+ path.m_offset[0] = XMVectorGetX(offset);
+ path.m_offset[1] = XMVectorGetY(offset);
+ path.m_offset[2] = XMVectorGetZ(offset);
+
+ float x0 = XMVectorGetX(screencenter);
+ float x1 = XMVectorGetX(screenpos);
+ txp = (+1.f - x0) / (x1 - x0);
+ txn = (-1.f - x0) / (x1 - x0);
+ }
+ path.m_timeBegin = txp / m_speed;
+ path.m_timeEnd = txn / m_speed;
+ path.m_time = path.m_timeBegin;
+
+ path.m_direction[0] = XMVectorGetX(worldDir);
+ path.m_direction[1] = XMVectorGetY(worldDir);
+ path.m_direction[2] = XMVectorGetZ(worldDir);
+ }
+ // set zeroth position
+ updatePosition(path, 0.f);
+ }
+}
+
+void Projectile::updateEmitterMode()
+{
+ if (m_fireBallMode)
+ {
+ if (m_prediction)
+ {
+ m_emitParams.allocationScale = { 1.f, 1.f, 1.f };
+ m_emitParams.allocationPredict = 0.4f;
+ }
+ else
+ {
+ m_emitParams.allocationScale = { 1.f, 1.f, 1.f };
+ m_emitParams.allocationPredict = 0.f;
+ }
+ m_temperature = 2.f;
+ m_fuel = 2.f;
+ }
+ else
+ {
+ m_emitParams.allocationScale = { 0.f, 0.f, 0.f };
+ m_emitParams.allocationPredict = 0.f;
+ m_temperature = 10.f;
+ m_fuel = 0.f;
+ }
+}
+
+void Projectile::imgui()
+{
+ if (imguiButton("Shoot", true))
+ {
+ shoot();
+ }
+ if (imguiCheck("Fire Ball", m_fireBallMode))
+ {
+ m_fireBallMode = !m_fireBallMode;
+ updateEmitterMode();
+ }
+ if (imguiSlider("Radius", &m_radius, 0.f, 1.f, 0.01f, true))
+ {
+ m_emitParams.bounds.x.x = m_radius;
+ m_emitParams.bounds.y.y = m_radius;
+ m_emitParams.bounds.z.z = m_radius;
+ }
+ imguiSlider("Speed", &m_speed, 0.f, 32.f, 0.1f, true);
+ imguiSlider("Temperature", &m_temperature, 0.f, 10.f, 0.1f, true);
+ if (m_fireBallMode)
+ {
+ imguiSlider("Fuel", &m_fuel, 0.f, 10.f, 0.1f, true);
+ if (imguiCheck("Prediction", m_prediction))
+ {
+ m_prediction = !m_prediction;
+ updateEmitterMode();
+ }
+ }
+ if (imguiCheck("Draw Projectile", m_shouldDrawMesh))
+ {
+ m_shouldDrawMesh = !m_shouldDrawMesh;
+ }
+}
+
+void Projectile::release()
+{
+ // set all projectiles inactive
+ for (int i = 0; i < m_pathsSize; i++)
+ {
+ Path& path = m_paths[i];
+ path.m_active = false;
+ }
+
+ NvFlowReleaseShapeSDF(m_shape);
+
+ MeshRelease(m_mesh);
+ MeshContextRelease(m_meshContext);
+} \ No newline at end of file