diff --git a/build.ps1 b/build.ps1 index f7ccdc0cf1..081e560773 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,5 +1,4 @@ -param( [string]$a ) -Write-Host $a +param( [string]$p, [string]$b) if (Get-Command "cmake" -errorAction SilentlyContinue) { @@ -41,7 +40,7 @@ if ($null -eq $env:VS_PATH) { Write-Output '$Env:VS_PATH="C:\Program Files\Microsoft Visual Studio\2022\Community"' $env:VS_PATH = Read-Host 'VS_PATH' - return; + # return; } } @@ -49,7 +48,7 @@ Import-Module ("$env:VS_PATH\\Common7\\Tools\\Microsoft.VisualStudio.DevShell.dl Enter-VsDevShell -VsInstallPath "${env:VS_PATH}" -SkipAutomaticLocation -DevCmdArguments "-arch=x64 -host_arch=x64" $shell_name = (Get-Process -Id $PID).name -echo $shell_name +Write-Host $shell_name # if ("pwsh" -eq $shell_name) { # cmd /K '"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" && pwsh.exe' @@ -57,17 +56,27 @@ echo $shell_name # cmd /K '"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" && powershell.exe' # } -if ($a.ToLower() -ne "full") { +if ($b.ToLower() -ne "debug") { + $b = "Release" +} else { + $b = "Debug" +} + +Write-Host $p +Write-Host $b + +if ($p.ToLower() -ne "full") { Write-Output "Making minimum build with Optix..." -cmake -G Ninja -B ninja -DCMAKE_BUILD_TYPE=Release ` +cmake -G Ninja -B build -DCMAKE_BUILD_TYPE="${b}" ` -DCMAKE_TOOLCHAIN_FILE="${env:VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" ` -DZENO_WITH_zenvdb:BOOL=ON ` - -DZENO_SYSTEM_OPENVDB=OFF ` + -DZENO_SYSTEM_OPENVDB:BOOL=OFF ` -DZENO_WITH_ZenoFX:BOOL=ON ` -DZENO_ENABLE_OPTIX:BOOL=ON ` -DZENO_WITH_FBX:BOOL=ON ` + -DZENO_WITH_Alembic:BOOL=ON ` -DZENO_WITH_MeshSubdiv:BOOL=ON ` -DCMAKE_EXPORT_COMPILE_COMMANDS=ON @@ -75,11 +84,12 @@ cmake -G Ninja -B ninja -DCMAKE_BUILD_TYPE=Release ` Write-Output "Making full build..." -cmake -G Ninja -B ninja -DCMAKE_BUILD_TYPE=Release ` +cmake -G Ninja -B build -DCMAKE_BUILD_TYPE="${b}" ` -DCMAKE_TOOLCHAIN_FILE="${env:VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" ` + -DZENO_WITH_CUDA:BOOL=ON ` -DZENO_WITH_ZenoFX:BOOL=ON ` -DZENO_ENABLE_OPTIX:BOOL=ON ` - -DZENO_SYSTEM_OPENVDB=OFF ` + -DZENO_SYSTEM_OPENVDB:BOOL=OFF ` -DZENOFX_ENABLE_OPENVDB:BOOL=ON ` -DZENOFX_ENABLE_LBVH:BOOL=ON ` -DZENO_WITH_zenvdb:BOOL=ON ` @@ -104,9 +114,12 @@ cmake -G Ninja -B ninja -DCMAKE_BUILD_TYPE=Release ` -DZENO_WITH_PBD:BOOL=ON ` -DZENO_WITH_GUI:BOOL=ON ` -DZENO_WITH_ImgCV:BOOL=ON ` + -DZENO_WITH_TOOL_FLIPtools:BOOL=ON ` + -DZENO_WITH_TOOL_cgmeshTools:BOOL=ON ` + -DZENO_WITH_TOOL_BulletTools:BOOL=ON ` + -DZENO_WITH_TOOL_HerculesTools:BOOL=ON ` -DCMAKE_EXPORT_COMPILE_COMMANDS=ON } -cmake --build ninja --config Release - -cp ./ninja/compile_commands.json ./ \ No newline at end of file +cmake --build build --config Release +cp ./build/compile_commands.json ./ \ No newline at end of file diff --git a/build.sh b/build.sh index af69067a25..c3af85b83f 100755 --- a/build.sh +++ b/build.sh @@ -8,6 +8,7 @@ cmake -B build -DCMAKE_BUILD_TYPE=$flag \ -DZENO_WITH_ZenoFX:BOOL=ON \ -DZENO_ENABLE_OPTIX:BOOL=ON \ -DZENO_WITH_FBX:BOOL=ON \ + -DZENO_WITH_Alembic:BOOL=ON \ -DZENO_WITH_MeshSubdiv:BOOL=ON \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ @@ -44,4 +45,6 @@ cmake -B build -DCMAKE_BUILD_TYPE=$flag \ cmake --build build --parallel $(nproc) \ # ln -s ./build/compile_commands.json ./ -cp ./build/compile_commands.json ./ \ No newline at end of file +cp ./build/compile_commands.json ./ + +rm -rf /var/tmp/OptixCache_$USER/ \ No newline at end of file diff --git a/misc/graphs/mis.zsg b/misc/graphs/mis.zsg new file mode 100644 index 0000000000..129a58be1f --- /dev/null +++ b/misc/graphs/mis.zsg @@ -0,0 +1,27659 @@ +{ + "graph": { + "main": { + "nodes": { + "3c0905fc-ShaderExtractVec": { + "name": "ShaderExtractVec", + "inputs": { + "vec": { + "link": "main:48de6969-ShaderInputAttr:[node]/outputs/out", + "type": "vec3f", + "default-value": null, + "control": { + "name": "Float Vector 3" + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "x": { + "type": "float" + }, + "y": { + "type": "float" + }, + "z": { + "type": "float" + }, + "w": { + "type": "float" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + -1756.5331012116386, + -250.06205749932975 + ], + "options": [] + }, + "48de6969-ShaderInputAttr": { + "name": "ShaderInputAttr", + "inputs": { + "attr": { + "link": null, + "type": "enum pos clr nrm uv tang bitang NoL LoV N T L V H reflectance fresnel instPos instNrm instUv instClr instTang prd.rndf() attrs.localPosLazy() attrs.uniformPosLazy()", + "default-value": "uv", + "control": { + "name": "Enum", + "items": [ + "pos", + "clr", + "nrm", + "uv", + "tang", + "bitang", + "NoL", + "LoV", + "N", + "T", + "L", + "V", + "H", + "reflectance", + "fresnel", + "instPos", + "instNrm", + "instUv", + "instClr", + "instTang", + "prd.rndf()", + "attrs.localPosLazy()", + "attrs.uniformPosLazy()" + ] + } + }, + "type": { + "link": null, + "type": "enum float vec2 vec3 vec4", + "default-value": "vec3", + "control": { + "name": "Enum", + "items": [ + "float", + "vec2", + "vec3", + "vec4" + ] + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "out": { + "type": "shader" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + -2655.59996627424, + -216.5530839825617 + ], + "options": [] + }, + "537b28e8-BindMaterial": { + "name": "BindMaterial", + "inputs": { + "object": { + "link": "main:a078517d-CreatePlane:[node]/outputs/prim", + "type": "", + "default-value": null, + "control": { + "name": "" + } + }, + "mtlid": { + "link": null, + "type": "string", + "default-value": "checker", + "control": { + "name": "String" + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "object": { + "type": "" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 3441.8097679412128, + 763.9007927700329 + ], + "options": [ + "VIEW" + ] + }, + "609d16d0-ShaderTernaryMath": { + "name": "ShaderTernaryMath", + "inputs": { + "in1": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "in2": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "in3": { + "link": "main:c0d26412-ShaderBinaryMath:[node]/outputs/out", + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "op": { + "link": null, + "type": "enum mix clamp smoothstep add3", + "default-value": "smoothstep", + "control": { + "name": "Enum", + "items": [ + "mix", + "clamp", + "smoothstep", + "add3" + ] + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "out": { + "type": "float" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 2811.447055656816, + -99.0531418717737 + ], + "options": [] + }, + "7dd1db0d-ShaderBinaryMath": { + "name": "ShaderBinaryMath", + "inputs": { + "in1": { + "link": "main:3c0905fc-ShaderExtractVec:[node]/outputs/y", + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "in2": { + "link": null, + "type": "float", + "default-value": 100.0, + "control": { + "name": "Float" + } + }, + "op": { + "link": null, + "type": "enum add sub mul div mod pow atan2 min max dot cross distance safepower", + "default-value": "mul", + "control": { + "name": "Enum", + "items": [ + "add", + "sub", + "mul", + "div", + "mod", + "pow", + "atan2", + "min", + "max", + "dot", + "cross", + "distance", + "safepower" + ] + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "out": { + "type": "float" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + -844.3340714711757, + 194.94755431237787 + ], + "options": [] + }, + "870767a0-ShaderBinaryMath": { + "name": "ShaderBinaryMath", + "inputs": { + "in1": { + "link": "main:7dd1db0d-ShaderBinaryMath:[node]/outputs/out", + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "in2": { + "link": null, + "type": "float", + "default-value": 1.5707999467849732, + "control": { + "name": "Float" + } + }, + "op": { + "link": null, + "type": "enum add sub mul div mod pow atan2 min max dot cross distance safepower", + "default-value": "add", + "control": { + "name": "Enum", + "items": [ + "add", + "sub", + "mul", + "div", + "mod", + "pow", + "atan2", + "min", + "max", + "dot", + "cross", + "distance", + "safepower" + ] + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "out": { + "type": "float" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 130.5814891246772, + 157.64609709725699 + ], + "options": [] + }, + "a078517d-CreatePlane": { + "name": "CreatePlane", + "inputs": { + "position": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + -100.0, + 0.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "scaleSize": { + "link": null, + "type": "vec3f", + "default-value": [ + 2000.0, + 2000.0, + 2000.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "rotate": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "hasNormal": { + "link": null, + "type": "bool", + "default-value": true, + "control": { + "name": "Boolean" + } + }, + "hasVertUV": { + "link": null, + "type": "bool", + "default-value": true, + "control": { + "name": "Boolean" + } + }, + "isFlipFace": { + "link": null, + "type": "bool", + "default-value": false, + "control": { + "name": "Boolean" + } + }, + "size": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "rows": { + "link": null, + "type": "int", + "default-value": 999, + "control": { + "name": "Integer" + } + }, + "columns": { + "link": null, + "type": "int", + "default-value": 999, + "control": { + "name": "Integer" + } + }, + "quads": { + "link": null, + "type": "bool", + "default-value": false, + "control": { + "name": "Boolean" + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "prim": { + "type": "" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 2708.661180520155, + 582.1687970874095 + ], + "options": [] + }, + "c0d26412-ShaderBinaryMath": { + "name": "ShaderBinaryMath", + "inputs": { + "in1": { + "link": "main:defa7f4e-ShaderUnaryMath:[node]/outputs/out", + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "in2": { + "link": "main:fa3178af-ShaderUnaryMath:[node]/outputs/out", + "type": "float", + "default-value": 1000.0, + "control": { + "name": "Float" + } + }, + "op": { + "link": null, + "type": "enum add sub mul div mod pow atan2 min max dot cross distance safepower", + "default-value": "mul", + "control": { + "name": "Enum", + "items": [ + "add", + "sub", + "mul", + "div", + "mod", + "pow", + "atan2", + "min", + "max", + "dot", + "cross", + "distance", + "safepower" + ] + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "out": { + "type": "float" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 2012.5181222746306, + -122.12792233571997 + ], + "options": [] + }, + "c4eb0fb4-ShaderTernaryMath": { + "name": "ShaderTernaryMath", + "inputs": { + "in1": { + "link": "main:609d16d0-ShaderTernaryMath:[node]/outputs/out", + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "in2": { + "link": null, + "type": "float", + "default-value": 0.20000000298023225, + "control": { + "name": "Float" + } + }, + "in3": { + "link": null, + "type": "float", + "default-value": 0.800000011920929, + "control": { + "name": "Float" + } + }, + "op": { + "link": null, + "type": "enum mix clamp smoothstep add3", + "default-value": "clamp", + "control": { + "name": "Enum", + "items": [ + "mix", + "clamp", + "smoothstep", + "add3" + ] + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "out": { + "type": "float" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 3716.2083489059207, + -11.966672454842666 + ], + "options": [] + }, + "dba0948f-ShaderBinaryMath": { + "name": "ShaderBinaryMath", + "inputs": { + "in1": { + "link": "main:3c0905fc-ShaderExtractVec:[node]/outputs/x", + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "in2": { + "link": null, + "type": "float", + "default-value": 100.0, + "control": { + "name": "Float" + } + }, + "op": { + "link": null, + "type": "enum add sub mul div mod pow atan2 min max dot cross distance safepower", + "default-value": "mul", + "control": { + "name": "Enum", + "items": [ + "add", + "sub", + "mul", + "div", + "mod", + "pow", + "atan2", + "min", + "max", + "dot", + "cross", + "distance", + "safepower" + ] + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "out": { + "type": "float" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + -836.1583730125941, + -405.84511084565659 + ], + "options": [] + }, + "defa7f4e-ShaderUnaryMath": { + "name": "ShaderUnaryMath", + "inputs": { + "in1": { + "link": "main:dba0948f-ShaderBinaryMath:[node]/outputs/out", + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "op": { + "link": null, + "type": "enum copy neg abs sqrt inversesqrt exp log sin cos tan asin acos atan degrees radians sinh cosh tanh asinh acosh atanh round roundEven floor ceil trunc sign step length normalize hsvToRgb rgbToHsv luminance", + "default-value": "sin", + "control": { + "name": "Enum", + "items": [ + "copy", + "neg", + "abs", + "sqrt", + "inversesqrt", + "exp", + "log", + "sin", + "cos", + "tan", + "asin", + "acos", + "atan", + "degrees", + "radians", + "sinh", + "cosh", + "tanh", + "asinh", + "acosh", + "atanh", + "round", + "roundEven", + "floor", + "ceil", + "trunc", + "sign", + "step", + "length", + "normalize", + "hsvToRgb", + "rgbToHsv", + "luminance" + ] + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "out": { + "type": "float" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 162.85517891010705, + -388.6265870371526 + ], + "options": [] + }, + "ef1af920-ShaderFinalize": { + "name": "ShaderFinalize", + "inputs": { + "base": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "basecolor": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 1.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "metallic": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "roughness": { + "link": "main:c4eb0fb4-ShaderTernaryMath:[node]/outputs/out", + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "specular": { + "link": null, + "type": "float", + "default-value": 0.5, + "control": { + "name": "Float" + } + }, + "subsurface": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "thickness": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "sssParam": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 1.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "sssColor": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 1.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "specularTint": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "anisotropic": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "anisoRotation": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "sheen": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "sheenTint": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "clearcoat": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "clearcoatGloss": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "clearcoatRoughness": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "clearcoatIOR": { + "link": null, + "type": "float", + "default-value": 1.5, + "control": { + "name": "Float" + } + }, + "specTrans": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "ior": { + "link": null, + "type": "float", + "default-value": 1.5, + "control": { + "name": "Float" + } + }, + "flatness": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "scatterDistance": { + "link": null, + "type": "float", + "default-value": 10000.0, + "control": { + "name": "Float" + } + }, + "scatterStep": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "thin": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "doubleSide": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "normal": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 0.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "displacement": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "smoothness": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "emissionIntensity": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "emission": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "reflectance": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 1.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "opacity": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "commonCode": { + "link": null, + "type": "string", + "default-value": "", + "control": { + "name": "String" + } + }, + "extensionsCode": { + "link": null, + "type": "string", + "default-value": "", + "control": { + "name": "String" + } + }, + "mtlid": { + "link": null, + "type": "string", + "default-value": "checker", + "control": { + "name": "String" + } + }, + "tex2dList": { + "property": "dict-panel", + "dictlist-panel": { + "collasped": false, + "keys": {} + }, + "link": null, + "type": "list", + "default-value": null, + "control": { + "name": "" + } + }, + "tex3dList": { + "property": "dict-panel", + "dictlist-panel": { + "collasped": false, + "keys": {} + }, + "link": null, + "type": "list", + "default-value": null, + "control": { + "name": "" + } + }, + "VolumeEmissionScaler": { + "link": null, + "type": "enum Raw Density Absorption", + "default-value": "Raw", + "control": { + "name": "Enum", + "items": [ + "Raw", + "Density", + "Absorption" + ] + } + }, + "vol_depth": { + "link": null, + "type": "float", + "default-value": 99.0, + "control": { + "name": "Float" + } + }, + "vol_extinction": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "vol_sample_albedo": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.5, + 0.5, + 0.5 + ], + "control": { + "name": "Float Vector 3" + } + }, + "vol_sample_anisotropy": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "vol_sample_density": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "vol_sample_emission": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": { + "backend": { + "value": "GLSL", + "control": { + "name": "Enum", + "items": [ + "GLSL", + "HLSL" + ] + }, + "type": "enum GLSL HLSL" + } + }, + "outputs": { + "mtl": { + "type": "MaterialObject" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 4683.016812965085, + -81.78545135176114 + ], + "options": [ + "VIEW" + ] + }, + "fa3178af-ShaderUnaryMath": { + "name": "ShaderUnaryMath", + "inputs": { + "in1": { + "link": "main:870767a0-ShaderBinaryMath:[node]/outputs/out", + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "op": { + "link": null, + "type": "enum copy neg abs sqrt inversesqrt exp log sin cos tan asin acos atan degrees radians sinh cosh tanh asinh acosh atanh round roundEven floor ceil trunc sign step length normalize hsvToRgb rgbToHsv luminance", + "default-value": "cos", + "control": { + "name": "Enum", + "items": [ + "copy", + "neg", + "abs", + "sqrt", + "inversesqrt", + "exp", + "log", + "sin", + "cos", + "tan", + "asin", + "acos", + "atan", + "degrees", + "radians", + "sinh", + "cosh", + "tanh", + "asinh", + "acosh", + "atanh", + "round", + "roundEven", + "floor", + "ceil", + "trunc", + "sign", + "step", + "length", + "normalize", + "hsvToRgb", + "rgbToHsv", + "luminance" + ] + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "out": { + "type": "float" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 1078.9644193034008, + 106.3481853080649 + ], + "options": [] + }, + "2c3a12de-CreatePlane": { + "name": "CreatePlane", + "inputs": { + "position": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "scaleSize": { + "link": null, + "type": "vec3f", + "default-value": [ + 100.0, + 100.0, + 20.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "rotate": { + "link": null, + "type": "vec3f", + "default-value": [ + 10.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "hasNormal": { + "link": null, + "type": "bool", + "default-value": false, + "control": { + "name": "Boolean" + } + }, + "hasVertUV": { + "link": null, + "type": "bool", + "default-value": false, + "control": { + "name": "Boolean" + } + }, + "isFlipFace": { + "link": null, + "type": "bool", + "default-value": false, + "control": { + "name": "Boolean" + } + }, + "size": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "rows": { + "link": null, + "type": "int", + "default-value": 1, + "control": { + "name": "Integer" + } + }, + "columns": { + "link": null, + "type": "int", + "default-value": 1, + "control": { + "name": "Integer" + } + }, + "quads": { + "link": null, + "type": "bool", + "default-value": false, + "control": { + "name": "Boolean" + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "prim": { + "type": "" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 2082.0198066520285, + 3323.674636305591 + ], + "options": [] + }, + "ac597f01-BindMaterial": { + "name": "BindMaterial", + "inputs": { + "object": { + "link": "main:2c3a12de-CreatePlane:[node]/outputs/prim", + "type": "", + "default-value": null, + "control": { + "name": "" + } + }, + "mtlid": { + "link": null, + "type": "string", + "default-value": "rough2", + "control": { + "name": "String" + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "object": { + "type": "" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 2745.873178064072, + 3506.5248497699569 + ], + "options": [ + "VIEW" + ] + }, + "c24a686f-CreatePlane": { + "name": "CreatePlane", + "inputs": { + "position": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 6.0, + 21.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "scaleSize": { + "link": null, + "type": "vec3f", + "default-value": [ + 100.0, + 100.0, + 20.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "rotate": { + "link": null, + "type": "vec3f", + "default-value": [ + 20.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "hasNormal": { + "link": null, + "type": "bool", + "default-value": false, + "control": { + "name": "Boolean" + } + }, + "hasVertUV": { + "link": null, + "type": "bool", + "default-value": false, + "control": { + "name": "Boolean" + } + }, + "isFlipFace": { + "link": null, + "type": "bool", + "default-value": false, + "control": { + "name": "Boolean" + } + }, + "size": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "rows": { + "link": null, + "type": "int", + "default-value": 1, + "control": { + "name": "Integer" + } + }, + "columns": { + "link": null, + "type": "int", + "default-value": 1, + "control": { + "name": "Integer" + } + }, + "quads": { + "link": null, + "type": "bool", + "default-value": false, + "control": { + "name": "Boolean" + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "prim": { + "type": "" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 3387.2896924275867, + 3355.9813735022046 + ], + "options": [] + }, + "de28b08a-BindMaterial": { + "name": "BindMaterial", + "inputs": { + "object": { + "link": "main:c24a686f-CreatePlane:[node]/outputs/prim", + "type": "", + "default-value": null, + "control": { + "name": "" + } + }, + "mtlid": { + "link": null, + "type": "string", + "default-value": "rough1", + "control": { + "name": "String" + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "object": { + "type": "" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 4086.5462541415947, + 3497.0958068994566 + ], + "options": [ + "VIEW" + ] + }, + "2d3300eb-BindMaterial": { + "name": "BindMaterial", + "inputs": { + "object": { + "link": "main:f87f3cf0-CreatePlane:[node]/outputs/prim", + "type": "", + "default-value": null, + "control": { + "name": "" + } + }, + "mtlid": { + "link": null, + "type": "string", + "default-value": "rough0", + "control": { + "name": "String" + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "object": { + "type": "" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 5386.970106537177, + 3465.3663569301168 + ], + "options": [ + "VIEW" + ] + }, + "f87f3cf0-CreatePlane": { + "name": "CreatePlane", + "inputs": { + "position": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 15.0, + 40.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "scaleSize": { + "link": null, + "type": "vec3f", + "default-value": [ + 100.0, + 100.0, + 20.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "rotate": { + "link": null, + "type": "vec3f", + "default-value": [ + 30.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "hasNormal": { + "link": null, + "type": "bool", + "default-value": false, + "control": { + "name": "Boolean" + } + }, + "hasVertUV": { + "link": null, + "type": "bool", + "default-value": false, + "control": { + "name": "Boolean" + } + }, + "isFlipFace": { + "link": null, + "type": "bool", + "default-value": false, + "control": { + "name": "Boolean" + } + }, + "size": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "rows": { + "link": null, + "type": "int", + "default-value": 1, + "control": { + "name": "Integer" + } + }, + "columns": { + "link": null, + "type": "int", + "default-value": 1, + "control": { + "name": "Integer" + } + }, + "quads": { + "link": null, + "type": "bool", + "default-value": false, + "control": { + "name": "Boolean" + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "prim": { + "type": "" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 4725.229781013748, + 3331.121814138215 + ], + "options": [] + }, + "a717ccb9-ShaderFinalize": { + "name": "ShaderFinalize", + "inputs": { + "base": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "basecolor": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 1.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "metallic": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "roughness": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "specular": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "subsurface": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "thickness": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "sssParam": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 1.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "sssColor": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 1.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "specularTint": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "anisotropic": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "anisoRotation": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "sheen": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "sheenTint": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "clearcoat": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "clearcoatGloss": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "clearcoatRoughness": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "clearcoatIOR": { + "link": null, + "type": "float", + "default-value": 1.5, + "control": { + "name": "Float" + } + }, + "specTrans": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "ior": { + "link": null, + "type": "float", + "default-value": 1.5, + "control": { + "name": "Float" + } + }, + "flatness": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "scatterDistance": { + "link": null, + "type": "float", + "default-value": 10000.0, + "control": { + "name": "Float" + } + }, + "scatterStep": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "thin": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "doubleSide": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "normal": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 0.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "displacement": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "smoothness": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "emissionIntensity": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "emission": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "reflectance": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 1.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "opacity": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "commonCode": { + "link": null, + "type": "string", + "default-value": "", + "control": { + "name": "String" + } + }, + "extensionsCode": { + "link": null, + "type": "string", + "default-value": "", + "control": { + "name": "String" + } + }, + "mtlid": { + "link": null, + "type": "string", + "default-value": "rough0", + "control": { + "name": "String" + } + }, + "tex2dList": { + "property": "dict-panel", + "dictlist-panel": { + "collasped": false, + "keys": {} + }, + "link": null, + "type": "list", + "default-value": null, + "control": { + "name": "" + } + }, + "tex3dList": { + "property": "dict-panel", + "dictlist-panel": { + "collasped": false, + "keys": {} + }, + "link": null, + "type": "list", + "default-value": null, + "control": { + "name": "" + } + }, + "VolumeEmissionScaler": { + "link": null, + "type": "enum Raw Density Absorption", + "default-value": "Raw", + "control": { + "name": "Enum", + "items": [ + "Raw", + "Density", + "Absorption" + ] + } + }, + "vol_depth": { + "link": null, + "type": "float", + "default-value": 99.0, + "control": { + "name": "Float" + } + }, + "vol_extinction": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "vol_sample_albedo": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.5, + 0.5, + 0.5 + ], + "control": { + "name": "Float Vector 3" + } + }, + "vol_sample_anisotropy": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "vol_sample_density": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "vol_sample_emission": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": { + "backend": { + "value": "GLSL", + "control": { + "name": "Enum", + "items": [ + "GLSL", + "HLSL" + ] + }, + "type": "enum GLSL HLSL" + } + }, + "outputs": { + "mtl": { + "type": "MaterialObject" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 5069.982531620115, + 4688.012047875876 + ], + "options": [ + "VIEW" + ] + }, + "c3da65e0-ShaderFinalize": { + "name": "ShaderFinalize", + "inputs": { + "base": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "basecolor": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 1.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "metallic": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "roughness": { + "link": null, + "type": "float", + "default-value": 0.20000000298023225, + "control": { + "name": "Float" + } + }, + "specular": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "subsurface": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "thickness": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "sssParam": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 1.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "sssColor": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 1.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "specularTint": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "anisotropic": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "anisoRotation": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "sheen": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "sheenTint": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "clearcoat": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "clearcoatGloss": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "clearcoatRoughness": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "clearcoatIOR": { + "link": null, + "type": "float", + "default-value": 1.5, + "control": { + "name": "Float" + } + }, + "specTrans": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "ior": { + "link": null, + "type": "float", + "default-value": 1.5, + "control": { + "name": "Float" + } + }, + "flatness": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "scatterDistance": { + "link": null, + "type": "float", + "default-value": 10000.0, + "control": { + "name": "Float" + } + }, + "scatterStep": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "thin": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "doubleSide": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "normal": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 0.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "displacement": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "smoothness": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "emissionIntensity": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "emission": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "reflectance": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 1.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "opacity": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "commonCode": { + "link": null, + "type": "string", + "default-value": "", + "control": { + "name": "String" + } + }, + "extensionsCode": { + "link": null, + "type": "string", + "default-value": "", + "control": { + "name": "String" + } + }, + "mtlid": { + "link": null, + "type": "string", + "default-value": "rough1", + "control": { + "name": "String" + } + }, + "tex2dList": { + "property": "dict-panel", + "dictlist-panel": { + "collasped": false, + "keys": {} + }, + "link": null, + "type": "list", + "default-value": null, + "control": { + "name": "" + } + }, + "tex3dList": { + "property": "dict-panel", + "dictlist-panel": { + "collasped": false, + "keys": {} + }, + "link": null, + "type": "list", + "default-value": null, + "control": { + "name": "" + } + }, + "VolumeEmissionScaler": { + "link": null, + "type": "enum Raw Density Absorption", + "default-value": "Raw", + "control": { + "name": "Enum", + "items": [ + "Raw", + "Density", + "Absorption" + ] + } + }, + "vol_depth": { + "link": null, + "type": "float", + "default-value": 99.0, + "control": { + "name": "Float" + } + }, + "vol_extinction": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "vol_sample_albedo": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.5, + 0.5, + 0.5 + ], + "control": { + "name": "Float Vector 3" + } + }, + "vol_sample_anisotropy": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "vol_sample_density": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "vol_sample_emission": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": { + "backend": { + "value": "GLSL", + "control": { + "name": "Enum", + "items": [ + "GLSL", + "HLSL" + ] + }, + "type": "enum GLSL HLSL" + } + }, + "outputs": { + "mtl": { + "type": "MaterialObject" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 4006.088000370115, + 4662.993737329001 + ], + "options": [ + "VIEW" + ] + }, + "9c90071-ShaderFinalize": { + "name": "ShaderFinalize", + "inputs": { + "base": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "basecolor": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 1.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "metallic": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "roughness": { + "link": null, + "type": "float", + "default-value": 0.30000001192092898, + "control": { + "name": "Float" + } + }, + "specular": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "subsurface": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "thickness": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "sssParam": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 1.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "sssColor": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 1.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "specularTint": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "anisotropic": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "anisoRotation": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "sheen": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "sheenTint": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "clearcoat": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "clearcoatGloss": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "clearcoatRoughness": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "clearcoatIOR": { + "link": null, + "type": "float", + "default-value": 1.5, + "control": { + "name": "Float" + } + }, + "specTrans": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "ior": { + "link": null, + "type": "float", + "default-value": 1.5, + "control": { + "name": "Float" + } + }, + "flatness": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "scatterDistance": { + "link": null, + "type": "float", + "default-value": 10000.0, + "control": { + "name": "Float" + } + }, + "scatterStep": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "thin": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "doubleSide": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "normal": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 0.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "displacement": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "smoothness": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "emissionIntensity": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "emission": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "reflectance": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 1.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "opacity": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "commonCode": { + "link": null, + "type": "string", + "default-value": "", + "control": { + "name": "String" + } + }, + "extensionsCode": { + "link": null, + "type": "string", + "default-value": "", + "control": { + "name": "String" + } + }, + "mtlid": { + "link": null, + "type": "string", + "default-value": "rough2", + "control": { + "name": "String" + } + }, + "tex2dList": { + "property": "dict-panel", + "dictlist-panel": { + "collasped": false, + "keys": {} + }, + "link": null, + "type": "list", + "default-value": null, + "control": { + "name": "" + } + }, + "tex3dList": { + "property": "dict-panel", + "dictlist-panel": { + "collasped": false, + "keys": {} + }, + "link": null, + "type": "list", + "default-value": null, + "control": { + "name": "" + } + }, + "VolumeEmissionScaler": { + "link": null, + "type": "enum Raw Density Absorption", + "default-value": "Raw", + "control": { + "name": "Enum", + "items": [ + "Raw", + "Density", + "Absorption" + ] + } + }, + "vol_depth": { + "link": null, + "type": "float", + "default-value": 99.0, + "control": { + "name": "Float" + } + }, + "vol_extinction": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "vol_sample_albedo": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.5, + 0.5, + 0.5 + ], + "control": { + "name": "Float Vector 3" + } + }, + "vol_sample_anisotropy": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "vol_sample_density": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "vol_sample_emission": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": { + "backend": { + "value": "GLSL", + "control": { + "name": "Enum", + "items": [ + "GLSL", + "HLSL" + ] + }, + "type": "enum GLSL HLSL" + } + }, + "outputs": { + "mtl": { + "type": "MaterialObject" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 2980.25621326074, + 4667.547204125876 + ], + "options": [ + "VIEW" + ] + }, + "41c56239-LightNode": { + "name": "LightNode", + "inputs": { + "position": { + "link": null, + "type": "vec3f", + "default-value": [ + -40.0, + 50.0, + 50.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "scale": { + "link": null, + "type": "vec3f", + "default-value": [ + 2.0, + 2.0, + 2.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "rotate": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "quaternion": { + "link": null, + "type": "vec4f", + "default-value": [ + 1.0, + 0.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 4" + } + }, + "color": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 0.10000000149011612, + 0.10000000149011612 + ], + "control": { + "name": "Float Vector 3" + } + }, + "exposure": { + "link": null, + "type": "float", + "default-value": 5.0, + "control": { + "name": "Float" + } + }, + "intensity": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "islight": { + "link": null, + "type": "bool", + "default-value": true, + "control": { + "name": "Boolean" + } + }, + "invertdir": { + "link": null, + "type": "bool", + "default-value": false, + "control": { + "name": "Boolean" + } + }, + "visible": { + "link": null, + "type": "bool", + "default-value": true, + "control": { + "name": "Boolean" + } + }, + "doubleside": { + "link": null, + "type": "bool", + "default-value": true, + "control": { + "name": "Boolean" + } + }, + "profile": { + "link": null, + "type": "string", + "default-value": "", + "control": { + "name": "String" + } + }, + "shape": { + "link": null, + "type": "enum Plane Sphere Point", + "default-value": "Plane", + "control": { + "name": "Enum", + "items": [ + "", + "Plane", + "Sphere", + "Point" + ] + } + }, + "type": { + "link": null, + "type": "enum Diffuse Direction IES", + "default-value": "Diffuse", + "control": { + "name": "Enum", + "items": [ + "", + "Diffuse", + "Direction", + "IES" + ] + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "prim": { + "type": "" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 8136.43048609757, + 156.14657051064985 + ], + "options": [ + "VIEW" + ] + }, + "f2315e61-CameraNode": { + "name": "CameraNode", + "inputs": { + "pos": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.32468482851982119, + 41.78123474121094, + -90.78573608398438 + ], + "control": { + "name": "Float Vector 3" + } + }, + "up": { + "link": null, + "type": "vec3f", + "default-value": [ + -0.0004980232333764434, + 0.9796715974807739, + 0.20060789585113526 + ], + "control": { + "name": "Float Vector 3" + } + }, + "view": { + "link": null, + "type": "vec3f", + "default-value": [ + -0.0024320962838828565, + -0.2006085216999054, + 0.9796685576438904 + ], + "control": { + "name": "Float Vector 3" + } + }, + "fov": { + "link": null, + "type": "float", + "default-value": 45.0, + "control": { + "name": "Float" + } + }, + "aperture": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "focalPlaneDistance": { + "link": null, + "type": "float", + "default-value": 2.0, + "control": { + "name": "Float" + } + }, + "other": { + "link": null, + "type": "string", + "default-value": "0,15,40,-0.201979,-3.13911,133.5,", + "control": { + "name": "String" + } + }, + "frame": { + "link": null, + "type": "int", + "default-value": 0, + "control": { + "name": "Integer" + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "camera": { + "type": "CameraObject" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 7373.914359961317, + 214.3704265049712 + ], + "options": [ + "VIEW" + ] + }, + "9897adc9-LightNode": { + "name": "LightNode", + "inputs": { + "position": { + "link": null, + "type": "vec3f", + "default-value": [ + -20.0, + 50.0, + 50.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "scale": { + "link": null, + "type": "vec3f", + "default-value": [ + 5.0, + 5.0, + 5.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "rotate": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "quaternion": { + "link": null, + "type": "vec4f", + "default-value": [ + 1.0, + 0.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 4" + } + }, + "color": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.10000000149011612, + 1.0, + 0.10000000149011612 + ], + "control": { + "name": "Float Vector 3" + } + }, + "exposure": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "intensity": { + "link": null, + "type": "float", + "default-value": 5.0, + "control": { + "name": "Float" + } + }, + "islight": { + "link": null, + "type": "bool", + "default-value": true, + "control": { + "name": "Boolean" + } + }, + "invertdir": { + "link": null, + "type": "bool", + "default-value": true, + "control": { + "name": "Boolean" + } + }, + "visible": { + "link": null, + "type": "bool", + "default-value": true, + "control": { + "name": "Boolean" + } + }, + "doubleside": { + "link": null, + "type": "bool", + "default-value": true, + "control": { + "name": "Boolean" + } + }, + "profile": { + "link": null, + "type": "string", + "default-value": "", + "control": { + "name": "String" + } + }, + "shape": { + "link": null, + "type": "enum Plane Sphere Point", + "default-value": "Sphere", + "control": { + "name": "Enum", + "items": [ + "", + "Plane", + "Sphere", + "Point" + ] + } + }, + "type": { + "link": null, + "type": "enum Diffuse Direction IES", + "default-value": "Diffuse", + "control": { + "name": "Enum", + "items": [ + "", + "Diffuse", + "Direction", + "IES" + ] + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "prim": { + "type": "" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 8971.454793057988, + -111.63185231041894 + ], + "options": [ + "VIEW" + ] + }, + "f175645-LightNode": { + "name": "LightNode", + "inputs": { + "position": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 50.0, + 50.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "scale": { + "link": null, + "type": "vec3f", + "default-value": [ + 10.0, + 10.0, + 10.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "rotate": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "quaternion": { + "link": null, + "type": "vec4f", + "default-value": [ + 1.0, + 0.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 4" + } + }, + "color": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 1.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "exposure": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "intensity": { + "link": null, + "type": "float", + "default-value": 7.0, + "control": { + "name": "Float" + } + }, + "islight": { + "link": null, + "type": "bool", + "default-value": true, + "control": { + "name": "Boolean" + } + }, + "invertdir": { + "link": null, + "type": "bool", + "default-value": true, + "control": { + "name": "Boolean" + } + }, + "visible": { + "link": null, + "type": "bool", + "default-value": true, + "control": { + "name": "Boolean" + } + }, + "doubleside": { + "link": null, + "type": "bool", + "default-value": true, + "control": { + "name": "Boolean" + } + }, + "profile": { + "link": null, + "type": "string", + "default-value": "", + "control": { + "name": "String" + } + }, + "shape": { + "link": null, + "type": "enum Plane Sphere Point", + "default-value": "Plane", + "control": { + "name": "Enum", + "items": [ + "", + "Plane", + "Sphere", + "Point" + ] + } + }, + "type": { + "link": null, + "type": "enum Diffuse Direction IES", + "default-value": "Diffuse", + "control": { + "name": "Enum", + "items": [ + "", + "Diffuse", + "Direction", + "IES" + ] + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "prim": { + "type": "" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 9807.894051206433, + 195.48607068197817 + ], + "options": [ + "VIEW" + ] + }, + "b98c5b9c-LightNode": { + "name": "LightNode", + "inputs": { + "position": { + "link": null, + "type": "vec3f", + "default-value": [ + 30.0, + 50.0, + 50.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "scale": { + "link": null, + "type": "vec3f", + "default-value": [ + 30.0, + 30.0, + 30.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "rotate": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "quaternion": { + "link": null, + "type": "vec4f", + "default-value": [ + 1.0, + 0.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 4" + } + }, + "color": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 0.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "exposure": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "intensity": { + "link": null, + "type": "float", + "default-value": 10.0, + "control": { + "name": "Float" + } + }, + "islight": { + "link": null, + "type": "bool", + "default-value": true, + "control": { + "name": "Boolean" + } + }, + "invertdir": { + "link": null, + "type": "bool", + "default-value": false, + "control": { + "name": "Boolean" + } + }, + "visible": { + "link": null, + "type": "bool", + "default-value": true, + "control": { + "name": "Boolean" + } + }, + "doubleside": { + "link": null, + "type": "bool", + "default-value": true, + "control": { + "name": "Boolean" + } + }, + "profile": { + "link": null, + "type": "string", + "default-value": "", + "control": { + "name": "String" + } + }, + "shape": { + "link": null, + "type": "enum Plane Sphere Point", + "default-value": "Sphere", + "control": { + "name": "Enum", + "items": [ + "", + "Plane", + "Sphere", + "Point" + ] + } + }, + "type": { + "link": null, + "type": "enum Diffuse Direction IES", + "default-value": "Diffuse", + "control": { + "name": "Enum", + "items": [ + "", + "Diffuse", + "Direction", + "IES" + ] + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "prim": { + "type": "" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 10628.778296366761, + -126.78143144093372 + ], + "options": [ + "VIEW" + ] + }, + "69ed03db-BindMaterial": { + "name": "BindMaterial", + "inputs": { + "object": { + "link": "main:dc975d92-CreatePlane:[node]/outputs/prim", + "type": "", + "default-value": null, + "control": { + "name": "" + } + }, + "mtlid": { + "link": null, + "type": "string", + "default-value": "checker", + "control": { + "name": "String" + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "object": { + "type": "" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 3488.170397896908, + 1720.0966652752705 + ], + "options": [ + "VIEW" + ] + }, + "dc975d92-CreatePlane": { + "name": "CreatePlane", + "inputs": { + "position": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 400.0, + 500.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "scaleSize": { + "link": null, + "type": "vec3f", + "default-value": [ + 2000.0, + 2000.0, + 2000.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "rotate": { + "link": null, + "type": "vec3f", + "default-value": [ + 90.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "hasNormal": { + "link": null, + "type": "bool", + "default-value": true, + "control": { + "name": "Boolean" + } + }, + "hasVertUV": { + "link": null, + "type": "bool", + "default-value": true, + "control": { + "name": "Boolean" + } + }, + "isFlipFace": { + "link": null, + "type": "bool", + "default-value": false, + "control": { + "name": "Boolean" + } + }, + "size": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "rows": { + "link": null, + "type": "int", + "default-value": 999, + "control": { + "name": "Integer" + } + }, + "columns": { + "link": null, + "type": "int", + "default-value": 999, + "control": { + "name": "Integer" + } + }, + "quads": { + "link": null, + "type": "bool", + "default-value": false, + "control": { + "name": "Boolean" + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "prim": { + "type": "" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 2742.015907576605, + 1567.9970571242712 + ], + "options": [] + }, + "b02f866f-ShaderFinalize": { + "name": "ShaderFinalize", + "inputs": { + "base": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "basecolor": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 1.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "metallic": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "roughness": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "specular": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "subsurface": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "thickness": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "sssParam": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 1.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "sssColor": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 1.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "specularTint": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "anisotropic": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "anisoRotation": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "sheen": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "sheenTint": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "clearcoat": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "clearcoatGloss": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "clearcoatRoughness": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "clearcoatIOR": { + "link": null, + "type": "float", + "default-value": 1.5, + "control": { + "name": "Float" + } + }, + "specTrans": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "ior": { + "link": null, + "type": "float", + "default-value": 1.5, + "control": { + "name": "Float" + } + }, + "flatness": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "scatterDistance": { + "link": null, + "type": "float", + "default-value": 10000.0, + "control": { + "name": "Float" + } + }, + "scatterStep": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "thin": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "doubleSide": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "normal": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 0.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "displacement": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "smoothness": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "emissionIntensity": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "emission": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "reflectance": { + "link": null, + "type": "vec3f", + "default-value": [ + 1.0, + 1.0, + 1.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "opacity": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "commonCode": { + "link": null, + "type": "string", + "default-value": "", + "control": { + "name": "String" + } + }, + "extensionsCode": { + "link": null, + "type": "string", + "default-value": "", + "control": { + "name": "String" + } + }, + "mtlid": { + "link": null, + "type": "string", + "default-value": "Mat1", + "control": { + "name": "String" + } + }, + "tex2dList": { + "property": "dict-panel", + "dictlist-panel": { + "collasped": false, + "keys": {} + }, + "link": null, + "type": "list", + "default-value": null, + "control": { + "name": "" + } + }, + "tex3dList": { + "property": "dict-panel", + "dictlist-panel": { + "collasped": false, + "keys": {} + }, + "link": null, + "type": "list", + "default-value": null, + "control": { + "name": "" + } + }, + "VolumeEmissionScaler": { + "link": null, + "type": "enum Raw Density Absorption", + "default-value": "Raw", + "control": { + "name": "Enum", + "items": [ + "Raw", + "Density", + "Absorption" + ] + } + }, + "vol_depth": { + "link": null, + "type": "float", + "default-value": 99.0, + "control": { + "name": "Float" + } + }, + "vol_extinction": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "vol_sample_albedo": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.5, + 0.5, + 0.5 + ], + "control": { + "name": "Float Vector 3" + } + }, + "vol_sample_anisotropy": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "vol_sample_density": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "vol_sample_emission": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": { + "backend": { + "value": "GLSL", + "control": { + "name": "Enum", + "items": [ + "GLSL", + "HLSL" + ] + }, + "type": "enum GLSL HLSL" + } + }, + "outputs": { + "mtl": { + "type": "MaterialObject" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 5500.180721416071, + -83.49885490595313 + ], + "options": [ + "VIEW" + ] + }, + "9a22105d-HDRSky": { + "name": "HDRSky", + "inputs": { + "enable": { + "link": null, + "type": "bool", + "default-value": false, + "control": { + "name": "Boolean" + } + }, + "path": { + "link": null, + "type": "readpath", + "default-value": null, + "control": { + "name": "read path" + } + }, + "rotation": { + "link": null, + "type": "float", + "default-value": 0.0, + "control": { + "name": "Float" + } + }, + "rotation3d": { + "link": null, + "type": "vec3f", + "default-value": [ + 0.0, + 0.0, + 0.0 + ], + "control": { + "name": "Float Vector 3" + } + }, + "strength": { + "link": null, + "type": "float", + "default-value": 1.0, + "control": { + "name": "Float" + } + }, + "SRC": { + "link": null, + "type": "", + "default-value": null, + "control": { + "name": "" + } + } + }, + "params": {}, + "outputs": { + "HDRSky": { + "type": "" + }, + "DST": { + "type": "" + } + }, + "uipos": [ + 6656.0884600564509, + 487.12836685064578 + ], + "options": [] + } + }, + "view_rect": {} + } + }, + "views": { + "timeline": { + "start-frame": 0, + "end-frame": 0, + "curr-frame": 0, + "always": false + } + }, + "descs": { + "AABBCollideDetect": { + "inputs": [ + [ + "vec3f", + "bminA", + "" + ], + [ + "vec3f", + "bmaxA", + "" + ], + [ + "vec3f", + "bminB", + "" + ], + [ + "vec3f", + "bmaxB", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "bool", + "overlap", + "" + ], + [ + "bool", + "AinsideB", + "" + ], + [ + "bool", + "BinsideA", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "math" + ] + }, + "AppendList": { + "inputs": [ + [ + "", + "list", + "" + ], + [ + "", + "object", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "list", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "list" + ] + }, + "Assign": { + "inputs": [ + [ + "", + "dst", + "" + ], + [ + "", + "src", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "dst", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "lifecycle" + ] + }, + "BVHNearestAttr": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "primNei", + "" + ], + [ + "string", + "bvhIdTag", + "bvh_id" + ], + [ + "string", + "bvhWeightTag", + "bvh_ws" + ], + [ + "string", + "bvhAttrTag", + "bvh_attr" + ], + [ + "enum float vec3f", + "bvhAttributesType", + "float" + ], + [ + "enum tris points", + "targetPrimType", + "tris" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "BVHNearestPos": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "primNei", + "" + ], + [ + "string", + "bvhIdTag", + "bvh_id" + ], + [ + "string", + "bvhWeightTag", + "bvh_ws" + ], + [ + "string", + "bvhPosTag", + "bvh_pos" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "BecomeRtInst": { + "inputs": [ + [ + "", + "object", + "" + ], + [ + "bool", + "isInst", + "1" + ], + [ + "string", + "instID", + "Inst1" + ], + [ + "enum XYZ YXZ YZX ZYX ZXY XZY", + "onbType", + "XYZ" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "object", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "BeginFor": { + "inputs": [ + [ + "int", + "count", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "int", + "index", + "" + ], + [ + "", + "FOR", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "control" + ] + }, + "BeginForEach": { + "inputs": [ + [ + "", + "list", + "" + ], + [ + "", + "accumate", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "object", + "" + ], + [ + "", + "accumate", + "" + ], + [ + "int", + "index", + "" + ], + [ + "", + "FOR", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "control" + ] + }, + "BeginSubstep": { + "inputs": [ + [ + "float", + "total_dt", + "" + ], + [ + "float", + "min_scale", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "FOR", + "" + ], + [ + "float", + "elapsed_time", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "control" + ] + }, + "BindLight": { + "inputs": [ + [ + "", + "object", + "" + ], + [ + "bool", + "islight", + "1" + ], + [ + "bool", + "invertdir", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "object", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "BindMaterial": { + "inputs": [ + [ + "", + "object", + "" + ], + [ + "string", + "mtlid", + "Mat1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "object", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "BindRtInst": { + "inputs": [ + [ + "", + "object", + "" + ], + [ + "string", + "instID", + "Inst1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "object", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "Blackboard": { + "inputs": [], + "params": [], + "outputs": [], + "categories": [ + "layout" + ] + }, + "BoundingBoxFitInto": { + "inputs": [ + [ + "vec3f", + "bminSrc", + "" + ], + [ + "vec3f", + "bmaxSrc", + "" + ], + [ + "vec3f", + "bminDst", + "" + ], + [ + "vec3f", + "bmaxDst", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "vec3f", + "translation", + "" + ], + [ + "vec3f", + "bminTrans", + "" + ], + [ + "vec3f", + "bmaxTrans", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "BreakFor": { + "inputs": [ + [ + "", + "FOR", + "" + ], + [ + "bool", + "breaks", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "control" + ] + }, + "BuildPrimitiveBvh": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "float", + "thickness", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum auto point line tri quad", + "prim_type", + "auto" + ] + ], + "outputs": [ + [ + "LBvh", + "lbvh", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "zenofx" + ] + }, + "CacheLastFrameBegin": { + "inputs": [ + [ + "", + "input", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "linkFrom", + "" + ], + [ + "", + "lastFrame", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "CacheLastFrameEnd": { + "inputs": [ + [ + "", + "linkTo", + "" + ], + [ + "", + "updateCache", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "output", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "CachePrimitive": { + "inputs": [ + [ + "", + "inPrim", + "" + ], + [ + "", + "frameNum", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "dir", + "/tmp/cache" + ], + [ + "bool", + "ignore", + "0" + ], + [ + "string", + "prefix", + "" + ] + ], + "outputs": [ + [ + "", + "outPrim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "CacheToDisk": { + "inputs": [ + [ + "", + "object", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "cachebasedir", + "" + ] + ], + "outputs": [ + [ + "", + "object", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "lifecycle" + ] + }, + "CacheVDBGrid": { + "inputs": [ + [ + "", + "inGrid", + "" + ], + [ + "", + "frameNum", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "dir", + "/tmp/cache" + ], + [ + "bool", + "ignore", + "0" + ], + [ + "bool", + "mute", + "0" + ], + [ + "string", + "prefix", + "" + ] + ], + "outputs": [ + [ + "", + "outGrid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "CachedByKey": { + "inputs": [ + [ + "", + "input", + "" + ], + [ + "", + "key", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "output", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "control" + ] + }, + "CachedIf": { + "inputs": [ + [ + "", + "input", + "" + ], + [ + "", + "keepCache", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "output", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "control" + ] + }, + "CachedOnce": { + "inputs": [ + [ + "", + "input", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "output", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "control" + ] + }, + "CalcCameraUp": { + "inputs": [ + [ + "vec3f", + "refUp", + "" + ], + [ + "vec3f", + "pos", + "" + ], + [ + "vec3f", + "target", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "vec3f", + "pos", + "" + ], + [ + "vec3f", + "up", + "" + ], + [ + "vec3f", + "view", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "CalcDirectionFromAngle": { + "inputs": [ + [ + "float", + "angle", + "" + ], + [ + "enum XY YX YZ ZY ZX XZ", + "plane", + "XY" + ], + [ + "float", + "length", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "vec3f", + "direction", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "math" + ] + }, + "CameraEval": { + "inputs": [ + [ + "", + "frameid", + "" + ], + [ + "", + "nodelist", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "CameraObject", + "camera", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "FBX" + ] + }, + "CameraNode": { + "inputs": [ + [ + "vec3f", + "pos", + "" + ], + [ + "vec3f", + "up", + "" + ], + [ + "vec3f", + "view", + "" + ], + [ + "float", + "fov", + "" + ], + [ + "float", + "aperture", + "" + ], + [ + "float", + "focalPlaneDistance", + "" + ], + [ + "string", + "other", + "" + ], + [ + "int", + "frame", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "CameraObject", + "camera", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "FBX" + ] + }, + "CihouMayaCameraFov": { + "inputs": [ + [ + "enum Horizontal Vertical", + "fit_gate", + "Horizontal" + ], + [ + "float", + "focL", + "" + ], + [ + "float", + "fw", + "" + ], + [ + "float", + "fh", + "" + ], + [ + "float", + "nx", + "" + ], + [ + "float", + "ny", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "float", + "fov", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "FBX" + ] + }, + "Clone": { + "inputs": [ + [ + "", + "object", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "newObject", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "lifecycle" + ] + }, + "CombineVDB": { + "inputs": [ + [ + "", + "FieldA", + "" + ], + [ + "", + "FieldB", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "float", + "MultiplierA", + "" + ], + [ + "float", + "MultiplierB", + "" + ], + [ + "enum CSGUnion CSGIntersection CSGDifference Add Mul Replace A_Sample_B", + "OpType", + "CSGUnion" + ], + [ + "bool", + "writeBack", + "0" + ] + ], + "outputs": [ + [ + "", + "FieldOut", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "CopyAllUserData": { + "inputs": [ + [ + "", + "dst", + "" + ], + [ + "", + "src", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "dst", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "lifecycle" + ] + }, + "CreateBezierCurve": { + "inputs": [ + [ + "list", + "CustomPoints", + "" + ], + [ + "prim", + "SamplePoints", + "" + ], + [ + "float", + "precision", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "SampleAttr", + "" + ], + [ + "string", + "SampleTag", + "" + ], + [ + "enum Bezier", + "Type", + "Bezier" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "curev", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "create" + ] + }, + "CreateCircle": { + "inputs": [ + [ + "int", + "segments", + "32" + ], + [ + "float", + "r", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "CreateCone": { + "inputs": [ + [ + "vec3f", + "position", + "" + ], + [ + "vec3f", + "scaleSize", + "" + ], + [ + "float", + "radius", + "" + ], + [ + "float", + "height", + "" + ], + [ + "int", + "lons", + "32" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "create" + ] + }, + "CreateCube": { + "inputs": [ + [ + "vec3f", + "position", + "" + ], + [ + "vec3f", + "scaleSize", + "" + ], + [ + "vec3f", + "rotate", + "" + ], + [ + "bool", + "hasNormal", + "0" + ], + [ + "bool", + "hasVertUV", + "0" + ], + [ + "bool", + "isFlipFace", + "0" + ], + [ + "int", + "div_w", + "2" + ], + [ + "int", + "div_h", + "2" + ], + [ + "int", + "div_d", + "2" + ], + [ + "float", + "size", + "" + ], + [ + "bool", + "quads", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "create" + ] + }, + "CreateCylinder": { + "inputs": [ + [ + "vec3f", + "position", + "" + ], + [ + "vec3f", + "scaleSize", + "" + ], + [ + "float", + "radius", + "" + ], + [ + "float", + "height", + "" + ], + [ + "int", + "lons", + "32" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "create" + ] + }, + "CreateDisk": { + "inputs": [ + [ + "vec3f", + "position", + "" + ], + [ + "vec3f", + "scaleSize", + "" + ], + [ + "vec3f", + "rotate", + "" + ], + [ + "bool", + "hasNormal", + "0" + ], + [ + "bool", + "hasVertUV", + "0" + ], + [ + "bool", + "isFlipFace", + "0" + ], + [ + "float", + "radius", + "" + ], + [ + "int", + "divisions", + "32" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "create" + ] + }, + "CreatePlane": { + "inputs": [ + [ + "vec3f", + "position", + "" + ], + [ + "vec3f", + "scaleSize", + "" + ], + [ + "vec3f", + "rotate", + "" + ], + [ + "bool", + "hasNormal", + "0" + ], + [ + "bool", + "hasVertUV", + "0" + ], + [ + "bool", + "isFlipFace", + "0" + ], + [ + "float", + "size", + "" + ], + [ + "int", + "rows", + "1" + ], + [ + "int", + "columns", + "1" + ], + [ + "bool", + "quads", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "create" + ] + }, + "CreatePoint": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "float", + "x", + "" + ], + [ + "float", + "y", + "" + ], + [ + "float", + "z", + "" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "create" + ] + }, + "CreatePrimCurve": { + "inputs": [ + [ + "prim", + "inputPoints", + "" + ], + [ + "float", + "precision", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum Bezier", + "Type", + "Bezier" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primCurve" + ] + }, + "CreateSphere": { + "inputs": [ + [ + "vec3f", + "position", + "" + ], + [ + "vec3f", + "scaleSize", + "" + ], + [ + "float", + "radius", + "" + ], + [ + "vec3f", + "rotate", + "" + ], + [ + "bool", + "hasNormal", + "0" + ], + [ + "bool", + "hasVertUV", + "0" + ], + [ + "bool", + "isFlipFace", + "0" + ], + [ + "int", + "rows", + "12" + ], + [ + "int", + "columns", + "24" + ], + [ + "bool", + "quads", + "0" + ], + [ + "bool", + "SphereRT", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "create" + ] + }, + "CreateTorus": { + "inputs": [ + [ + "vec3f", + "position", + "" + ], + [ + "vec3f", + "rotate", + "" + ], + [ + "float", + "MajorRadius", + "" + ], + [ + "float", + "MinorRadius", + "" + ], + [ + "bool", + "hasNormal", + "0" + ], + [ + "bool", + "hasVertUV", + "0" + ], + [ + "int", + "MajorSegment", + "48" + ], + [ + "int", + "MinorSegment", + "12" + ], + [ + "bool", + "quads", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "create" + ] + }, + "CreateTube": { + "inputs": [ + [ + "vec3f", + "position", + "" + ], + [ + "vec3f", + "scaleSize", + "" + ], + [ + "vec3f", + "rotate", + "" + ], + [ + "bool", + "hasNormal", + "0" + ], + [ + "bool", + "hasVertUV", + "0" + ], + [ + "bool", + "isFlipFace", + "0" + ], + [ + "float", + "radius1", + "" + ], + [ + "float", + "radius2", + "" + ], + [ + "float", + "height", + "" + ], + [ + "int", + "rows", + "3" + ], + [ + "int", + "columns", + "12" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "create" + ] + }, + "CurveOrientation": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "string", + "dirName", + "dir" + ], + [ + "string", + "tanName", + "tan" + ], + [ + "string", + "bitanName", + "bitan" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "Curvemap": { + "inputs": [ + [ + "", + "curvemap", + "" + ], + [ + "", + "value", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "res", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "DegreetoRad": { + "inputs": [ + [ + "float", + "degree", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "float", + "radian", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "math" + ] + }, + "DelUserData": { + "inputs": [ + [ + "", + "object", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "key", + "" + ] + ], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "DelUserData2": { + "inputs": [ + [ + "string", + "key", + "" + ], + [ + "", + "object", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "object", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "lifecycle" + ] + }, + "DictEraseItem": { + "inputs": [ + [ + "DictObject", + "dict", + "" + ], + [ + "string", + "key", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "DictObject", + "dict", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "WBTest" + ] + }, + "DictGetItem": { + "inputs": [ + [ + "DictObject", + "dict", + "" + ], + [ + "string", + "key", + "" + ], + [ + "IObject", + "defl", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "zany", + "object", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "dict" + ] + }, + "DictGetKeyList": { + "inputs": [ + [ + "DictObject", + "dict", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "ListObject", + "keys", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "dict" + ] + }, + "DictHasKey": { + "inputs": [ + [ + "DictObject", + "dict", + "" + ], + [ + "string", + "key", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "bool", + "hasKey", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "dict" + ] + }, + "DictSetItem": { + "inputs": [ + [ + "DictObject", + "dict", + "" + ], + [ + "string", + "key", + "" + ], + [ + "zany", + "object", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "DictObject", + "dict", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "dict" + ] + }, + "DictSize": { + "inputs": [ + [ + "DictObject", + "dict", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "int", + "size", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "dict" + ] + }, + "DictUnion": { + "inputs": [ + [ + "DictObject", + "dict1", + "" + ], + [ + "DictObject", + "dict2", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "DictObject", + "dict", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "dict" + ] + }, + "DynamicNumber": { + "inputs": [ + [ + "", + "frame", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum 100 10 1 0.1 0.01 0.001", + "speed", + "1" + ], + [ + "enum clamp zero cycle", + "type", + "clamp" + ], + [ + "floatslider", + "w", + "0" + ], + [ + "floatslider", + "x", + "0" + ], + [ + "floatslider", + "y", + "0" + ], + [ + "floatslider", + "z", + "0" + ] + ], + "outputs": [ + [ + "", + "vec3", + "" + ], + [ + "", + "x", + "" + ], + [ + "", + "y", + "" + ], + [ + "", + "z", + "" + ], + [ + "", + "w", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "EmbedZsgGraph": { + "inputs": [ + [ + "readpath", + "zsgPath", + "" + ], + [ + "dict", + "argsDict", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "dict", + "retsDict", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "subgraph" + ] + }, + "EmptyDict": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "DictObject", + "dict", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "dict" + ] + }, + "EmptyList": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "list", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "list" + ] + }, + "EndFor": { + "inputs": [ + [ + "", + "FOR", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "control" + ] + }, + "EndForEach": { + "inputs": [ + [ + "", + "object", + "" + ], + [ + "", + "list", + "" + ], + [ + "", + "accumate", + "" + ], + [ + "bool", + "accept", + "1" + ], + [ + "", + "FOR", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "doConcat", + "0" + ] + ], + "outputs": [ + [ + "", + "list", + "" + ], + [ + "", + "droppedList", + "" + ], + [ + "", + "accumate", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "control" + ] + }, + "EvalBlenderFile": { + "inputs": [ + [ + "readpath", + "script_file", + "" + ], + [ + "readpath", + "blender_file", + "" + ], + [ + "readpath", + "output_path", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "fake", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "FBX" + ] + }, + "EvalCurve": { + "inputs": [ + [ + "float", + "value", + "" + ], + [ + "curve", + "curve", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "float", + "value", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "curve" + ] + }, + "EvalCurveOnPrimAttr": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "string", + "attrName", + "tmp" + ], + [ + "string", + "dstName", + "" + ], + [ + "curve", + "curve", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "curve" + ] + }, + "EvalFBXAnim": { + "inputs": [ + [ + "", + "frameid", + "" + ], + [ + "", + "data", + "" + ], + [ + "", + "animinfo", + "" + ], + [ + "", + "nodetree", + "" + ], + [ + "", + "bonetree", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "evalBlendShape", + "0" + ], + [ + "enum TRUE FALSE", + "interAnimData", + "TRUE" + ], + [ + "bool", + "printAnimData", + "0" + ], + [ + "enum FROM_MAYA DEFAULT", + "unit", + "FROM_MAYA" + ], + [ + "bool", + "writeData", + "0" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "camera", + "" + ], + [ + "", + "light", + "" + ], + [ + "", + "matName", + "" + ], + [ + "", + "meshName", + "" + ], + [ + "", + "pathName", + "" + ], + [ + "", + "bsPrimsOrigin", + "" + ], + [ + "list", + "bsPrims", + "" + ], + [ + "", + "transDict", + "" + ], + [ + "", + "quatDict", + "" + ], + [ + "", + "scaleDict", + "" + ], + [ + "", + "writeData", + "" + ], + [ + "", + "visibility", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "FBX" + ] + }, + "ExchangeFBXData": { + "inputs": [ + [ + "", + "d", + "" + ], + [ + "", + "animinfo", + "" + ], + [ + "", + "nodetree", + "" + ], + [ + "", + "bonetree", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum DATA DATAS MATS", + "dType", + "DATA" + ] + ], + "outputs": [ + [ + "", + "d", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "FBX" + ] + }, + "ExportFBX": { + "inputs": [ + [ + "string", + "custom_command", + "" + ], + [ + "string", + "extra_param", + " -b=5" + ], + [ + "string", + "abcpath", + "" + ], + [ + "string", + "fbxpath", + "" + ], + [ + "string", + "outpath", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "result", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "FBX" + ] + }, + "ExportObjPrimitive": { + "inputs": [ + [ + "writepath", + "path", + "" + ], + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "ExportVDBGrid": { + "inputs": [ + [ + "", + "data", + "" + ], + [ + "", + "path", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "ExportZpmPrimitive": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "writepath", + "path", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "ExtendList": { + "inputs": [ + [ + "", + "list1", + "" + ], + [ + "", + "list2", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "list", + "list1", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "list" + ] + }, + "ExtractAxis": { + "inputs": [ + [ + "AxisObject", + "math", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "vec3f", + "origin", + "" + ], + [ + "vec3f", + "axisX", + "" + ], + [ + "vec3f", + "axisY", + "" + ], + [ + "vec3f", + "axisZ", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "math" + ] + }, + "ExtractCameraData": { + "inputs": [ + [ + "string", + "key", + "camera1" + ], + [ + "", + "camobject", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "pos", + "" + ], + [ + "", + "up", + "" + ], + [ + "", + "view", + "" + ], + [ + "", + "focL", + "" + ], + [ + "", + "haov", + "" + ], + [ + "", + "waov", + "" + ], + [ + "", + "hfov", + "" + ], + [ + "", + "filmW", + "" + ], + [ + "", + "filmH", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "FBX" + ] + }, + "ExtractDict": { + "inputs": [ + [ + "DictObject", + "dict", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "dict" + ] + }, + "ExtractFBXData": { + "inputs": [ + [ + "FBXData", + "data", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "IVertices", + "vertices", + "" + ], + [ + "IIndices", + "indices", + "" + ], + [ + "IMaterial", + "material", + "" + ], + [ + "IBoneOffset", + "boneOffset", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "FBX" + ] + }, + "ExtractLegacyDict": { + "inputs": [ + [ + "DictObject", + "dict", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "ExtractList": { + "inputs": [ + [ + "", + "list", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "list" + ] + }, + "ExtractMatData": { + "inputs": [ + [ + "", + "data", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "list", + "datas", + "" + ], + [ + "", + "matName", + "" + ], + [ + "list", + "texLists", + "" + ], + [ + "dict", + "texMaps", + "" + ], + [ + "dict", + "matValues", + "" + ], + [ + "dict", + "texUvs", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "FBX" + ] + }, + "ExtractMatDict": { + "inputs": [ + [ + "IMaterial", + "material", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "mats", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "FBX" + ] + }, + "ExtractMatName": { + "inputs": [ + [ + "", + "material", + "" + ], + [ + "", + "key", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "name", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "FBX" + ] + }, + "ExtractMatTexList": { + "inputs": [ + [ + "IMaterial", + "material", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "texLists", + "" + ], + [ + "", + "name", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "FBX" + ] + }, + "FileReadString": { + "inputs": [ + [ + "readpath", + "path", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "string", + "str", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "string" + ] + }, + "FileWriteString": { + "inputs": [ + [ + "string", + "str", + "" + ], + [ + "writepath", + "path", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "string" + ] + }, + "FuncBegin": { + "inputs": [ + [ + "", + "extraArgs", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "args", + "" + ], + [ + "", + "FUNC", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "control" + ] + }, + "FuncCall": { + "inputs": [ + [ + "FunctionObject", + "function", + "" + ], + [ + "FunctionObject", + "args", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "FunctionObject", + "rets", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "control" + ] + }, + "FuncCallInDict": { + "inputs": [ + [ + "DictObject", + "funcDict", + "" + ], + [ + "bool", + "mayNotFound", + "1" + ], + [ + "string", + "dictKey", + "" + ], + [ + "DictObject", + "args", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "DictObject", + "rets", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "control" + ] + }, + "FuncEnd": { + "inputs": [ + [ + "", + "rets", + "" + ], + [ + "", + "FUNC", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "function", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "control" + ] + }, + "FuncSimpleBegin": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "arg", + "" + ], + [ + "", + "FUNC", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "control" + ] + }, + "FuncSimpleCall": { + "inputs": [ + [ + "FunctionObject", + "function", + "" + ], + [ + "IObject", + "arg", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "IObject", + "ret", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "control" + ] + }, + "FuncSimpleCallInDict": { + "inputs": [ + [ + "DictObject", + "funcDict", + "" + ], + [ + "string", + "dictKey", + "" + ], + [ + "IObject", + "arg", + "" + ], + [ + "bool", + "mayNotFound", + "1" + ], + [ + "IObject", + "notFoundRet", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "bool", + "isFound", + "" + ], + [ + "IObject", + "ret", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "control" + ] + }, + "FuncSimpleEnd": { + "inputs": [ + [ + "", + "ret", + "" + ], + [ + "", + "FUNC", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "function", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "control" + ] + }, + "Gather2DFiniteDifference": { + "inputs": [ + [ + "PrimitiveObject", + "grid", + "" + ], + [ + "int", + "nx", + "1" + ], + [ + "int", + "ny", + "1" + ], + [ + "string", + "channel", + "pos" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum FIVE_STENCIL NINE_STENCIL", + "OpType", + "FIVE_STENCIL" + ], + [ + "enum vec3 float", + "attrT", + "float" + ] + ], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "zenofx" + ] + }, + "GetCurveControlPoint": { + "inputs": [ + [ + "curve", + "curve", + "" + ], + [ + "string", + "key", + "x" + ], + [ + "int", + "index", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "float", + "point_x", + "" + ], + [ + "float", + "point_y", + "" + ], + [ + "vec2f", + "left_handler", + "" + ], + [ + "vec2f", + "right_handler", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "curve" + ] + }, + "GetFrameNum": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "FrameNum", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "frame" + ] + }, + "GetFramePortion": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "FramePortion", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "frame" + ] + }, + "GetFrameTime": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "time", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "frame" + ] + }, + "GetFrameTimeElapsed": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "time", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "frame" + ] + }, + "GetPerlinNoise": { + "inputs": [ + [ + "vec3f", + "vec3", + "" + ], + [ + "", + "seed", + "" + ], + [ + "float", + "freq", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "noise", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "noise" + ] + }, + "GetTime": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "time", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "frame" + ] + }, + "GetUserData": { + "inputs": [ + [ + "", + "object", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "key", + "" + ] + ], + "outputs": [ + [ + "", + "data", + "" + ], + [ + "bool", + "hasValue", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "GetUserData2": { + "inputs": [ + [ + "", + "object", + "" + ], + [ + "string", + "key", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "data", + "" + ], + [ + "bool", + "hasValue", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "lifecycle" + ] + }, + "GetVDBBound": { + "inputs": [ + [ + "", + "vdbGrid", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "vec3f", + "bmin", + "" + ], + [ + "vec3f", + "bmax", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "GetVDBPoints": { + "inputs": [ + [ + "", + "grid", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "pars", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "GetVDBPointsDroplets": { + "inputs": [ + [ + "", + "grid", + "" + ], + [ + "", + "sdf", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "GetVDBVoxelSize": { + "inputs": [ + [ + "", + "vdbGrid", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "dx", + "" + ], + [ + "", + "dy", + "" + ], + [ + "", + "dz", + "" + ], + [ + "", + "dxyz", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "Grid2DSample": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "PrimitiveObject", + "sampleGrid", + "" + ], + [ + "int", + "nx", + "1" + ], + [ + "int", + "ny", + "1" + ], + [ + "float", + "h", + "" + ], + [ + "vec3f", + "bmin", + "" + ], + [ + "string", + "channel", + "*" + ], + [ + "string", + "sampleBy", + "pos" + ], + [ + "enum Clamp Periodic", + "sampleType", + "Clamp" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "zenofx" + ] + }, + "Grid2DSample_M": { + "inputs": [ + [ + "PrimitiveObject", + "grid", + "" + ], + [ + "PrimitiveObject", + "grid2", + "" + ], + [ + "int", + "nx", + "1" + ], + [ + "int", + "ny", + "1" + ], + [ + "float", + "h", + "" + ], + [ + "vec3f", + "bmin", + "" + ], + [ + "string", + "channel", + "pos" + ], + [ + "string", + "sampleBy", + "pos" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum vec3 float", + "attrT", + "float" + ] + ], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "WBTest" + ] + }, + "Group": { + "inputs": [], + "params": [], + "outputs": [], + "categories": [ + "layout" + ] + }, + "HDRSky": { + "inputs": [ + [ + "bool", + "enable", + "1" + ], + [ + "readpath", + "path", + "" + ], + [ + "float", + "rotation", + "" + ], + [ + "vec3f", + "rotation3d", + "" + ], + [ + "float", + "strength", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "HDRSky", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "HF_maskByFeature": { + "inputs": [ + [ + "", + "HeightField", + "" + ], + [ + "bool", + "invert_mask", + "0" + ], + [ + "string", + "height_layer", + "height" + ], + [ + "string", + "mask_layer", + "mask" + ], + [ + "int", + "smooth_radius", + "1" + ], + [ + "bool", + "use_slope", + "0" + ], + [ + "float", + "min_slopeangle", + "" + ], + [ + "float", + "max_slopeangle", + "" + ], + [ + "curve", + "slope_ramp", + "" + ], + [ + "bool", + "use_direction", + "0" + ], + [ + "float", + "goal_angle", + "" + ], + [ + "float", + "angle_spread", + "" + ], + [ + "curve", + "dir_ramp", + "" + ], + [ + "bool", + "use_height", + "0" + ], + [ + "float", + "min_height", + "" + ], + [ + "float", + "max_height", + "" + ], + [ + "curve", + "height_ramp", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "HeightField", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "HF_maskbyOcclusion": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "bool", + "invert mask", + "0" + ], + [ + "int", + "view distance", + "200" + ], + [ + "float", + "step scale", + "" + ], + [ + "int", + "num of searches", + "16" + ], + [ + "bool", + "dohemisphere", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "HF_remap": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "string", + "remap layer", + "height" + ], + [ + "float", + "input min", + "" + ], + [ + "float", + "input max", + "" + ], + [ + "float", + "output min", + "" + ], + [ + "float", + "output max", + "" + ], + [ + "curve", + "remap ramp", + "" + ], + [ + "bool", + "clamp min", + "0" + ], + [ + "bool", + "clamp max", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "HF_rotate_displacement_2d": { + "inputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "float", + "Rotate Displacement", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "HeatmapFromImage": { + "inputs": [ + [ + "", + "image", + "" + ], + [ + "int", + "startPos", + "0" + ], + [ + "int", + "endPos", + "-1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "heatmap", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "visualize" + ] + }, + "HeightStarPattern": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "float", + "rotate", + "" + ], + [ + "float", + "anglerandom", + "" + ], + [ + "float", + "shapesize", + "" + ], + [ + "float", + "posjitter", + "" + ], + [ + "float", + "sharpness", + "" + ], + [ + "float", + "starness", + "" + ], + [ + "int", + "sides", + "5" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "HelperMute": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "NOTE", + "Dont-use-this-node-directly" + ] + ], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "HelperOnce": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "NOTE", + "Dont-use-this-node-directly" + ] + ], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "INTERN_PreViewVDB": { + "inputs": [ + [ + "", + "arg0", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "ret0", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "IfElse": { + "inputs": [ + [ + "", + "true", + "" + ], + [ + "", + "false", + "" + ], + [ + "bool", + "cond", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "result", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "control" + ] + }, + "ImageFlipVertical": { + "inputs": [ + [ + "", + "image", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "image", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "comp" + ] + }, + "ImageFloatGaussianBlur": { + "inputs": [ + [ + "", + "image", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "image", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "comp" + ] + }, + "ImportObjPrimitive": { + "inputs": [ + [ + "readpath", + "path", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "ImportVDBGrid": { + "inputs": [ + [ + "", + "path", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "type", + "" + ] + ], + "outputs": [ + [ + "", + "data", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "ImportZpmPrimitive": { + "inputs": [ + [ + "readpath", + "path", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "IntegrateFrameTime": { + "inputs": [ + [ + "", + "desired_dt", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "float", + "min_scale", + "" + ] + ], + "outputs": [ + [ + "", + "actual_dt", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "frame" + ] + }, + "IsList": { + "inputs": [ + [ + "", + "list", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "result", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "list" + ] + }, + "LightNode": { + "inputs": [ + [ + "vec3f", + "position", + "" + ], + [ + "vec3f", + "scale", + "" + ], + [ + "vec3f", + "rotate", + "" + ], + [ + "vec4f", + "quaternion", + "" + ], + [ + "vec3f", + "color", + "" + ], + [ + "float", + "exposure", + "" + ], + [ + "float", + "intensity", + "" + ], + [ + "bool", + "islight", + "1" + ], + [ + "bool", + "invertdir", + "1" + ], + [ + "bool", + "visible", + "0" + ], + [ + "bool", + "doubleside", + "0" + ], + [ + "string", + "profile", + "" + ], + [ + "enum Plane Sphere Point", + "shape", + "Plane" + ], + [ + "enum Diffuse Direction IES", + "type", + "Diffuse" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "LineAddVert": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "vert", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "LineCarve": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "float", + "insertU", + "" + ], + [ + "bool", + "cut", + "0" + ], + [ + "bool", + "cut insert to end", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "LineResample": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "int", + "segments", + "3" + ], + [ + "", + "PrimSampler", + "" + ], + [ + "string", + "SampleBy", + "t" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "ListGetItem": { + "inputs": [ + [ + "", + "list", + "" + ], + [ + "int", + "index", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "object", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "list" + ] + }, + "ListLength": { + "inputs": [ + [ + "", + "list", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "length", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "list" + ] + }, + "LiveMeshNode": { + "inputs": [ + [ + "", + "frameid", + "" + ], + [ + "string", + "vertSrc", + "" + ], + [ + "bool", + "outDict", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prims", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "FBX" + ] + }, + "Make1DLinePrimitive": { + "inputs": [ + [ + "int", + "n", + "2" + ], + [ + "vec3f", + "direction", + "" + ], + [ + "float", + "scale", + "" + ], + [ + "vec3f", + "origin", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum X Y Z", + "Direction", + "X" + ], + [ + "bool", + "hasLines", + "1" + ], + [ + "bool", + "isCentered", + "0" + ] + ], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "Make2DGridPrimitive": { + "inputs": [ + [ + "int", + "nx", + "2" + ], + [ + "int", + "ny", + "0" + ], + [ + "vec3f", + "sizeX", + "" + ], + [ + "vec3f", + "sizeY", + "" + ], + [ + "float", + "scale", + "" + ], + [ + "vec3f", + "origin", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum XZ XY YZ", + "Direction", + "XZ" + ], + [ + "enum Column-major Row-major", + "Layout", + "Column-major" + ], + [ + "bool", + "hasFaces", + "1" + ], + [ + "bool", + "hasUV", + "0" + ], + [ + "bool", + "isCentered", + "0" + ] + ], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "Make3DGridPointsInAABB": { + "inputs": [ + [ + "int", + "nx", + "4" + ], + [ + "int", + "ny", + "0" + ], + [ + "int", + "nz", + "0" + ], + [ + "vec3f", + "bmin", + "" + ], + [ + "vec3f", + "bmax", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "isStaggered", + "1" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "Make3DGridPrimitive": { + "inputs": [ + [ + "int", + "nx", + "2" + ], + [ + "int", + "ny", + "0" + ], + [ + "int", + "nz", + "0" + ], + [ + "vec3f", + "sizeX", + "" + ], + [ + "vec3f", + "sizeY", + "" + ], + [ + "vec3f", + "sizeZ", + "" + ], + [ + "float", + "scale", + "" + ], + [ + "vec3f", + "origin", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "isCentered", + "0" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "MakeAxis": { + "inputs": [ + [ + "vec3f", + "origin", + "" + ], + [ + "vec3f", + "axisX", + "" + ], + [ + "vec3f", + "axisY", + "" + ], + [ + "vec3f", + "axisZ", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum off X Y Z", + "normalize", + "off" + ] + ], + "outputs": [ + [ + "AxisObject", + "math", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "math" + ] + }, + "MakeBoxPrimitive": { + "inputs": [ + [ + "float", + "size_x", + "" + ], + [ + "float", + "size_y", + "" + ], + [ + "float", + "size_z", + "" + ], + [ + "vec3f", + "origin", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "use_quads", + "0" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "MakeCamera": { + "inputs": [ + [ + "vec3f", + "pos", + "" + ], + [ + "vec3f", + "up", + "" + ], + [ + "vec3f", + "view", + "" + ], + [ + "float", + "near", + "" + ], + [ + "float", + "far", + "" + ], + [ + "float", + "fov", + "" + ], + [ + "float", + "aperture", + "" + ], + [ + "float", + "focalPlaneDistance", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "CameraObject", + "camera", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "MakeCubePrimitive": { + "inputs": [ + [ + "", + "spacing", + "" + ], + [ + "", + "nx", + "" + ], + [ + "", + "ny", + "" + ], + [ + "", + "nz", + "" + ], + [ + "", + "origin", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "MakeCurve": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "curve", + "curve", + "" + ] + ], + "outputs": [ + [ + "curve", + "curve", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "curve" + ] + }, + "MakeCurvemap": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "float", + "input_max", + "" + ], + [ + "float", + "input_min", + "" + ], + [ + "float", + "output_max", + "" + ], + [ + "float", + "output_min", + "" + ] + ], + "outputs": [ + [ + "", + "curvemap", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "MakeDict": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "DictObject", + "dict", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "dict" + ] + }, + "MakeDummy": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "dummy", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "layout" + ] + }, + "MakeGCTest": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "int", + "value", + "42" + ] + ], + "outputs": [ + [ + "", + "value", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "debug" + ] + }, + "MakeHeatmap": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "int", + "nres", + "1024" + ] + ], + "outputs": [ + [ + "", + "heatmap", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "visualize" + ] + }, + "MakeInstancing": { + "inputs": [ + [ + "int", + "amount", + "1" + ], + [ + "list", + "modelMatrices", + "" + ], + [ + "float", + "deltaTime", + "" + ], + [ + "list", + "timeList", + "" + ], + [ + "list", + "framePrims", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "instancing", + "inst", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "MakeLight": { + "inputs": [ + [ + "vec3f", + "lightDir", + "" + ], + [ + "float", + "intensity", + "" + ], + [ + "vec3f", + "shadowTint", + "" + ], + [ + "float", + "lightHight", + "" + ], + [ + "float", + "shadowSoftness", + "" + ], + [ + "vec3f", + "lightColor", + "" + ], + [ + "float", + "lightScale", + "" + ], + [ + "bool", + "isEnabled", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "LightObject", + "light", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "MakeList": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "doConcat", + "1" + ] + ], + "outputs": [ + [ + "", + "list", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "list" + ] + }, + "MakeLocalSys": { + "inputs": [ + [ + "vec3f", + "front", + "" + ], + [ + "vec3f", + "up", + "" + ], + [ + "vec3f", + "right", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "LocalSys", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "math" + ] + }, + "MakeMultilineString": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "multiline_string", + "value", + "" + ] + ], + "outputs": [ + [ + "string", + "value", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "string" + ] + }, + "MakeOrthonormalBase": { + "inputs": [ + [ + "vec3f", + "normal", + "" + ], + [ + "vec3f", + "tangent", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "vec3f", + "normal", + "" + ], + [ + "vec3f", + "tangent", + "" + ], + [ + "vec3f", + "bitangent", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "math" + ] + }, + "MakePointPrimitive": { + "inputs": [ + [ + "", + "vec3", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "MakePrimitive": { + "inputs": [ + [ + "int", + "size", + "0" + ], + [ + "string", + "points", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "MakePrimitiveFromList": { + "inputs": [ + [ + "ListObject", + "list", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "MakeReadPath": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "readpath", + "path", + "" + ] + ], + "outputs": [ + [ + "string", + "path", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "string" + ] + }, + "MakeShaderUniform": { + "inputs": [ + [ + "int", + "size", + "512" + ], + [ + "", + "uniformDict", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "MakeSmallDict": { + "inputs": [ + [ + "string", + "key0", + "" + ], + [ + "IObject", + "obj0", + "" + ], + [ + "string", + "key1", + "" + ], + [ + "IObject", + "obj1", + "" + ], + [ + "string", + "key2", + "" + ], + [ + "IObject", + "obj2", + "" + ], + [ + "string", + "key3", + "" + ], + [ + "IObject", + "obj3", + "" + ], + [ + "string", + "key4", + "" + ], + [ + "IObject", + "obj4", + "" + ], + [ + "string", + "key5", + "" + ], + [ + "IObject", + "obj5", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "dict", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "dict" + ] + }, + "MakeSmallList": { + "inputs": [ + [ + "", + "obj0", + "" + ], + [ + "", + "obj1", + "" + ], + [ + "", + "obj2", + "" + ], + [ + "", + "obj3", + "" + ], + [ + "", + "obj4", + "" + ], + [ + "", + "obj5", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "doConcat", + "1" + ] + ], + "outputs": [ + [ + "", + "list", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "list" + ] + }, + "MakeString": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "value", + "" + ] + ], + "outputs": [ + [ + "string", + "value", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "string" + ] + }, + "MakeTexture2D": { + "inputs": [ + [ + "readpath", + "path", + "" + ], + [ + "", + "heatmap", + "" + ], + [ + "enum REPEAT MIRRORED_REPEAT CLAMP_TO_EDGE CLAMP_TO_BORDER", + "wrapS", + "REPEAT" + ], + [ + "enum REPEAT MIRRORED_REPEAT CLAMP_TO_EDGE CLAMP_TO_BORDER", + "wrapT", + "REPEAT" + ], + [ + "enum NEAREST LINEAR NEAREST_MIPMAP_NEAREST LINEAR_MIPMAP_NEAREST NEAREST_MIPMAP_LINEAR LINEAR_MIPMAP_LINEAR", + "minFilter", + "LINEAR" + ], + [ + "enum NEAREST LINEAR NEAREST_MIPMAP_NEAREST LINEAR_MIPMAP_NEAREST NEAREST_MIPMAP_LINEAR LINEAR_MIPMAP_LINEAR", + "magFilter", + "LINEAR" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "texture", + "tex", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "MakeTextureVDB": { + "inputs": [ + [ + "readpath", + "path", + "" + ], + [ + "string", + "channel", + "0" + ], + [ + "enum Fp32 Fp16 Fp8 Fp4", + "type", + "Fp32" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "texture", + "tex", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "MakeVDBGrid": { + "inputs": [ + [ + "float", + "Dx", + "" + ], + [ + "float", + "background", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "name", + "" + ], + [ + "enum vertex Centered Staggered", + "structure", + "Centered" + ], + [ + "enum float float3 int int3 points", + "type", + "float" + ] + ], + "outputs": [ + [ + "", + "data", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "MakeVisualAABBPrimitive": { + "inputs": [ + [ + "float", + "dx", + "" + ], + [ + "vec3f", + "boundMin", + "" + ], + [ + "vec3f", + "boundMax", + "" + ], + [ + "int", + "OpenTop", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum points edges trifaces quadfaces", + "type", + "edges" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "visualize" + ] + }, + "MakeWritePath": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "writepath", + "path", + "" + ] + ], + "outputs": [ + [ + "string", + "path", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "string" + ] + }, + "MatTranspose": { + "inputs": [ + [ + "", + "mat", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "transposeMat", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "math" + ] + }, + "MeshToSDF": { + "inputs": [ + [ + "", + "mesh", + "" + ], + [ + "float", + "Dx", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum vertex cell", + "type", + "vertex" + ], + [ + "float", + "voxel_size", + "" + ] + ], + "outputs": [ + [ + "", + "sdf", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "MocDictAsOutput": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "DictObject", + "dict", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "dict2" + ] + }, + "MomentumTransfer2DFiniteDifference": { + "inputs": [ + [ + "PrimitiveObject", + "grid", + "" + ], + [ + "int", + "nx", + "1" + ], + [ + "int", + "ny", + "1" + ], + [ + "string", + "channel", + "d" + ], + [ + "string", + "add_channel", + "d" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum FIVE_STENCIL NINE_STENCIL", + "OpType", + "FIVE_STENCIL" + ], + [ + "enum vec3 float", + "attrT", + "float" + ] + ], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "zenofx" + ] + }, + "MoveAssign": { + "inputs": [ + [ + "", + "dst", + "" + ], + [ + "", + "src", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "dst", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "lifecycle" + ] + }, + "MoveClone": { + "inputs": [ + [ + "", + "object", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "newObject", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "lifecycle" + ] + }, + "MoveDelete": { + "inputs": [ + [ + "", + "object", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "lifecycle" + ] + }, + "MultiMakeDict": { + "inputs": [ + [ + "DictObject", + "dict", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "dict", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "dict" + ] + }, + "MultiMakeList": { + "inputs": [ + [ + "list", + "list", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "list", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "list" + ] + }, + "MustReadObjPrim": { + "inputs": [ + [ + "readpath", + "path", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "triangulate", + "1" + ] + ], + "outputs": [ + [ + "primitive", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "Noise_gabor_2d": { + "inputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "string", + "posLikeAttrName", + "pos" + ], + [ + "float", + "a_", + "" + ], + [ + "float", + "frequency", + "" + ], + [ + "float", + "Orientation", + "" + ], + [ + "int", + "impulses_per_kernel", + "64" + ], + [ + "bool", + "isotropic", + "0" + ], + [ + "float", + "offset", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attrName", + "noise" + ] + ], + "outputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "NumRandom": { + "inputs": [ + [ + "vec3f", + "dir", + "" + ], + [ + "float", + "base", + "" + ], + [ + "float", + "scale", + "" + ], + [ + "int", + "seed", + "-1" + ], + [ + "enum scalar01 scalar11 cube01 cube11 plane01 plane11 disk cylinder ball semiball sphere semisphere", + "randType", + "scalar01" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "int", + "value", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "numeric" + ] + }, + "NumRandomFloat": { + "inputs": [ + [ + "int", + "seed", + "-1" + ], + [ + "float", + "valmin", + "" + ], + [ + "float", + "valmax", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "float", + "value", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "numeric" + ] + }, + "NumRandomInt": { + "inputs": [ + [ + "int", + "seed", + "-1" + ], + [ + "int", + "valmin", + "0" + ], + [ + "int", + "valmax", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "int", + "value", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "numeric" + ] + }, + "NumRandomSeedCombine": { + "inputs": [ + [ + "int", + "x", + "0" + ], + [ + "int", + "y", + "0" + ], + [ + "int", + "z", + "0" + ], + [ + "int", + "w", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "int", + "seed", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "numeric" + ] + }, + "NumericCounter": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "int", + "count", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "numeric" + ] + }, + "NumericEval": { + "inputs": [ + [ + "string", + "zfxCode", + "" + ], + [ + "enum float vec3f int string", + "resType", + "float" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "float", + "result", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "numeric" + ] + }, + "NumericFloat": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "float", + "value", + "" + ] + ], + "outputs": [ + [ + "float", + "value", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "numeric" + ] + }, + "NumericInt": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "int", + "value", + "0" + ] + ], + "outputs": [ + [ + "int", + "value", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "numeric" + ] + }, + "NumericIntVec2": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "int", + "x", + "0" + ], + [ + "int", + "y", + "0" + ] + ], + "outputs": [ + [ + "vec2i", + "vec2", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "numeric" + ] + }, + "NumericIntVec3": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "int", + "x", + "0" + ], + [ + "int", + "y", + "0" + ], + [ + "int", + "z", + "0" + ] + ], + "outputs": [ + [ + "vec3i", + "vec3", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "numeric" + ] + }, + "NumericIntVec4": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "float", + "w", + "" + ], + [ + "float", + "x", + "" + ], + [ + "float", + "y", + "" + ], + [ + "float", + "z", + "" + ] + ], + "outputs": [ + [ + "vec4f", + "vec4", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "numeric" + ] + }, + "NumericInterpolation": { + "inputs": [ + [ + "NumericObject", + "src", + "" + ], + [ + "NumericObject", + "srcMin", + "" + ], + [ + "NumericObject", + "srcMax", + "" + ], + [ + "NumericObject", + "dstMin", + "" + ], + [ + "NumericObject", + "dstMax", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "isClamped", + "0" + ] + ], + "outputs": [ + [ + "NumericObject", + "dst", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "numeric" + ] + }, + "NumericOperator": { + "inputs": [ + [ + "NumericObject", + "lhs", + "" + ], + [ + "NumericObject", + "rhs", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum add sub mul div mod and or xor shr shl cmpge cmple cmpgt cmplt cmpne cmpeq land lor pos neg inv not atan2 pow max min fmod dot cross distance length normalize abs sqrt sin cos tan asin acos atan exp log floor ceil toint tofloat anytrue alltrue copy copyr", + "op_type", + "add" + ] + ], + "outputs": [ + [ + "NumericObject", + "ret", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "numeric" + ] + }, + "NumericRandom": { + "inputs": [ + [ + "float", + "scale", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "int", + "dim", + "1" + ], + [ + "bool", + "symmetric", + "0" + ] + ], + "outputs": [ + [ + "NumericObject", + "value", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "NumericRandomInt": { + "inputs": [ + [ + "int", + "min", + "0" + ], + [ + "int", + "max", + "65536" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "int", + "value", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "NumericRangeList": { + "inputs": [ + [ + "int", + "start", + "0" + ], + [ + "int", + "end", + "1" + ], + [ + "int", + "skip", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "list", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "list" + ] + }, + "NumericVec2": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "float", + "x", + "" + ], + [ + "float", + "y", + "" + ] + ], + "outputs": [ + [ + "vec2f", + "vec2", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "numeric" + ] + }, + "NumericVec3": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "float", + "x", + "" + ], + [ + "float", + "y", + "" + ], + [ + "float", + "z", + "" + ] + ], + "outputs": [ + [ + "vec3f", + "vec3", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "numeric" + ] + }, + "NumericVec4": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "float", + "w", + "" + ], + [ + "float", + "x", + "" + ], + [ + "float", + "y", + "" + ], + [ + "float", + "z", + "" + ] + ], + "outputs": [ + [ + "vec4f", + "vec4", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "numeric" + ] + }, + "NumericWrangle": { + "inputs": [ + [ + "DictObject:NumericObject", + "params", + "" + ], + [ + "string", + "zfxCode", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "DictObject:NumericObject", + "result", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "zenofx" + ] + }, + "OSDPrimSubdiv": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "int", + "levels", + "2" + ], + [ + "string", + "edgeCreaseAttr", + "" + ], + [ + "bool", + "triangulate", + "1" + ], + [ + "bool", + "asQuadFaces", + "1" + ], + [ + "bool", + "hasLoopUVs", + "1" + ], + [ + "bool", + "copyFaceAttrs", + "1" + ], + [ + "bool", + "delayTillIpc", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "ObjTimeShift": { + "inputs": [ + [ + "IObject", + "obj", + "" + ], + [ + "int", + "offset", + "1" + ], + [ + "ListObject", + "customList", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "IObject", + "obj", + "" + ], + [ + "IObject", + "prevObj", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "OrthonormalBase": { + "inputs": [ + [ + "vec3f", + "normal", + "" + ], + [ + "vec3f", + "tangent", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "vec3f", + "normal", + "" + ], + [ + "vec3f", + "tangent", + "" + ], + [ + "vec3f", + "bitangent", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "math" + ] + }, + "PackNumericIntVec2": { + "inputs": [ + [ + "int", + "x", + "0" + ], + [ + "int", + "y", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "vec2i", + "vec2", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "numeric" + ] + }, + "PackNumericVec": { + "inputs": [ + [ + "float", + "x", + "" + ], + [ + "float", + "y", + "" + ], + [ + "float", + "z", + "" + ], + [ + "float", + "w", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum float vec2f vec3f vec4f", + "type", + "vec3f" + ] + ], + "outputs": [ + [ + "", + "vec", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "numeric" + ] + }, + "PackNumericVecInt": { + "inputs": [ + [ + "int", + "x", + "0" + ], + [ + "int", + "y", + "0" + ], + [ + "int", + "z", + "0" + ], + [ + "int", + "w", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum int vec2i vec3i vec4i", + "type", + "vec3i" + ] + ], + "outputs": [ + [ + "", + "veci", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "numeric" + ] + }, + "ParamFileParser": { + "inputs": [ + [ + "", + "formatList", + "" + ], + [ + "writepath", + "configFilePath", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "DictObject", + "params", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "string" + ] + }, + "ParamFormat": { + "inputs": [ + [ + "string", + "name", + "" + ], + [ + "enum float vec2f vec3f vec4f int vec2i vec3i vec4i string", + "type", + "string" + ], + [ + "string", + "defaultValue", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "format", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "string" + ] + }, + "ParameterizeLine": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "ParticleAsVoxels": { + "inputs": [ + [ + "VDBGrid", + "vdbGrid", + "" + ], + [ + "string", + "Attr", + "" + ], + [ + "", + "particles", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "oGrid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "visualize" + ] + }, + "ParticleParticleWrangle": { + "inputs": [ + [ + "PrimitiveObject", + "prim1", + "" + ], + [ + "PrimitiveObject", + "prim2", + "" + ], + [ + "string", + "zfxCode", + "" + ], + [ + "DictObject:NumericObject", + "params", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "zenofx" + ] + }, + "ParticleToLevelSet": { + "inputs": [ + [ + "", + "Particles", + "" + ], + [ + "float", + "Radius", + "" + ], + [ + "float", + "Dx", + "" + ], + [ + "string", + "rname", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "SurfaceSDF", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "ParticlesBuildBvh": { + "inputs": [ + [ + "PrimitiveObject", + "primNei", + "" + ], + [ + "float", + "radius", + "" + ], + [ + "float", + "radiusMin", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "LBvh", + "lbvh", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "zenofx" + ] + }, + "ParticlesBuildBvhRadius": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "float", + "basicRadius", + "" + ], + [ + "string", + "radiusAttr", + "" + ], + [ + "string", + "neiRadiusAttr", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "LBvh", + "lbvh", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "zenofx" + ] + }, + "ParticlesBuildHashGrid": { + "inputs": [ + [ + "PrimitiveObject", + "primNei", + "" + ], + [ + "numeric:float", + "radius", + "" + ], + [ + "numeric:float", + "radiusMin", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "hashgrid", + "hashGrid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "zenofx" + ] + }, + "ParticlesMaskedWrangle": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "string", + "zfxCode", + "" + ], + [ + "DictObject:NumericObject", + "params", + "" + ], + [ + "string", + "maskAttr", + "mask" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "zenofx" + ] + }, + "ParticlesNeighborBvhRadiusWrangle": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "PrimitiveObject", + "primNei", + "" + ], + [ + "LBvh", + "lbvh", + "" + ], + [ + "bool", + "is_box", + "0" + ], + [ + "string", + "radiusAttr", + "radius" + ], + [ + "string", + "neighborRadiusAttr", + "neighborRadius" + ], + [ + "string", + "maskAttr", + "" + ], + [ + "string", + "zfxCode", + "" + ], + [ + "DictObject:NumericObject", + "params", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "zenofx" + ] + }, + "ParticlesNeighborBvhWrangle": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "PrimitiveObject", + "primNei", + "" + ], + [ + "LBvh", + "lbvh", + "" + ], + [ + "bool", + "is_box", + "1" + ], + [ + "string", + "zfxCode", + "" + ], + [ + "DictObject:NumericObject", + "params", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "zenofx" + ] + }, + "ParticlesNeighborBvhWrangleSorted": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "PrimitiveObject", + "primNei", + "" + ], + [ + "LBvh", + "lbvh", + "" + ], + [ + "bool", + "is_box", + "1" + ], + [ + "int", + "limit", + "-1" + ], + [ + "string", + "zfxCode", + "" + ], + [ + "DictObject:NumericObject", + "params", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "zenofx" + ] + }, + "ParticlesNeighborWrangle": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "PrimitiveObject", + "primNei", + "" + ], + [ + "HashGrid", + "hashGrid", + "" + ], + [ + "string", + "zfxCode", + "" + ], + [ + "DictObject:NumericObject", + "params", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "zenofx" + ] + }, + "ParticlesTwoWrangle": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "PrimitiveObject", + "prim2", + "" + ], + [ + "string", + "zfxCode", + "" + ], + [ + "DictObject:NumericObject", + "params", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "zenofx" + ] + }, + "ParticlesWrangle": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "string", + "zfxCode", + "" + ], + [ + "DictObject:NumericObject", + "params", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "zenofx" + ] + }, + "PixarOrthonormalBase": { + "inputs": [ + [ + "vec3f", + "normal", + "" + ], + [ + "vec3f", + "tangent", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "vec3f", + "normal", + "" + ], + [ + "vec3f", + "tangent", + "" + ], + [ + "vec3f", + "bitangent", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "math" + ] + }, + "PlaneProjectPrimitive2DAABB": { + "inputs": [ + [ + "", + "origin", + "" + ], + [ + "", + "normal", + "" + ], + [ + "", + "tangent", + "" + ], + [ + "", + "bitangent", + "" + ], + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "boundMin2D", + "" + ], + [ + "", + "boundMax2D", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "math" + ] + }, + "PortalIn": { + "inputs": [ + [ + "", + "port", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "name", + "RenameMe!" + ] + ], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "layout" + ] + }, + "PortalOut": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "name", + "RenameMe!" + ] + ], + "outputs": [ + [ + "", + "port", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "layout" + ] + }, + "PrimAttrInterp": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "PrimitiveObject", + "prim2", + "" + ], + [ + "string", + "attr", + "" + ], + [ + "float", + "factor", + "" + ], + [ + "string", + "facAttr", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimAttribBlur": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "enum line tri", + "primType", + "tri" + ], + [ + "string", + "attributes", + "ratio" + ], + [ + "enum float vec3f ", + "attributesType", + "float" + ], + [ + "bool", + "useEdgeLengthWeight", + "0" + ], + [ + "int", + "blurringIterations", + "0" + ], + [ + "enum laplacian VolumePreserving custom", + "mode", + "laplacian" + ], + [ + "float", + "stepSize", + "" + ], + [ + "float", + "cutoffFrequency", + "" + ], + [ + "float", + "evenStepSize", + "" + ], + [ + "float", + "oddStepSize", + "" + ], + [ + "string", + "weightAttributes", + "weight" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primCurve" + ] + }, + "PrimBarycentricInterp": { + "inputs": [ + [ + "", + "Particles", + "" + ], + [ + "", + "MeshPrim", + "" + ], + [ + "string", + "triIdTag", + "bvh_id" + ], + [ + "string", + "weightTag", + "bvh_ws" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "Particles", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimBend": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "vec3f", + "tangent", + "" + ], + [ + "vec3f", + "direction", + "" + ], + [ + "float", + "angle", + "" + ], + [ + "float", + "limitMin", + "" + ], + [ + "float", + "limitMax", + "" + ], + [ + "float", + "midPoint", + "" + ], + [ + "float", + "biasDir", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimBoundingBox": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "float", + "extraBound", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "vec3f", + "bmin", + "" + ], + [ + "vec3f", + "bmax", + "" + ], + [ + "vec3f", + "center", + "" + ], + [ + "vec3f", + "radius", + "" + ], + [ + "vec3f", + "diameter", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimCalcCentroid": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "enum Volume Area Vertex BoundBox", + "method", + "Volume" + ], + [ + "float", + "density", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "vec3f", + "centroid", + "" + ], + [ + "float", + "mass", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimCheckTagInRange": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "string", + "tagAttr", + "index" + ], + [ + "int", + "beg", + "0" + ], + [ + "int", + "end", + "0" + ], + [ + "bool", + "endExcluded", + "0" + ], + [ + "int", + "modularBy", + "0" + ], + [ + "int", + "trueVal", + "1" + ], + [ + "int", + "falseVal", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimColorByTag": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "string", + "tagAttr", + "tag" + ], + [ + "string", + "clrAttr", + "clr" + ], + [ + "int", + "seed", + "-1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "visualize" + ] + }, + "PrimConnectBridge": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "string", + "edgeIndAttr", + "tag" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimConnectSkin": { + "inputs": [ + [ + "ListObject", + "primList", + "" + ], + [ + "bool", + "isCloseRing", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimConnectTape": { + "inputs": [ + [ + "PrimitiveObject", + "prim1", + "" + ], + [ + "PrimitiveObject", + "prim2", + "" + ], + [ + "enum quads lines none", + "faceType", + "quads" + ], + [ + "bool", + "isCloseRing", + "0" + ], + [ + "string", + "edgeMaskAttr", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimCopyAttr": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "string", + "sourceName", + "s" + ], + [ + "string", + "targetName", + "t" + ], + [ + "enum float vec2f vec3f vec4f int vec2i vec3i vec4i", + "type", + "float" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "PrimCurveDir": { + "inputs": [ + [ + "", + "prim_curve", + "" + ], + [ + "string", + "dirName", + "nrm" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim_curve", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primCurve" + ] + }, + "PrimCurveFromVerts": { + "inputs": [ + [ + "", + "primVerts", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "primCurve", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primCurve" + ] + }, + "PrimDecodeUVs": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "PrimDualMesh": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "bool", + "polygonate", + "1" + ], + [ + "bool", + "keepBounds", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimDuplicate": { + "inputs": [ + [ + "PrimitiveObject", + "parsPrim", + "" + ], + [ + "PrimitiveObject", + "meshPrim", + "" + ], + [ + "string", + "dirAttr", + "" + ], + [ + "string", + "tanAttr", + "" + ], + [ + "string", + "radAttr", + "" + ], + [ + "enum XYZ YXZ YZX ZYX ZXY XZY", + "onbType", + "XYZ" + ], + [ + "float", + "radius", + "" + ], + [ + "bool", + "copyParsAttr", + "1" + ], + [ + "bool", + "copyMeshAttr", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimDuplicateConnLines": { + "inputs": [ + [ + "PrimitiveObject", + "parsPrim", + "" + ], + [ + "PrimitiveObject", + "meshPrim", + "" + ], + [ + "string", + "dirAttr", + "" + ], + [ + "string", + "tanAttr", + "" + ], + [ + "string", + "radAttr", + "" + ], + [ + "enum XYZ YXZ YZX ZYX ZXY XZY", + "onbType", + "XYZ" + ], + [ + "float", + "radius", + "" + ], + [ + "bool", + "copyParsAttr", + "1" + ], + [ + "bool", + "copyMeshAttr", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimEdgeBound": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "bool", + "removeFaces", + "1" + ], + [ + "bool", + "killDeadVerts", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimExtrude": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "string", + "maskAttr", + "" + ], + [ + "float", + "extrude", + "" + ], + [ + "float", + "inset", + "" + ], + [ + "vec3f", + "offset", + "" + ], + [ + "string", + "sourceMaskAttrO", + "" + ], + [ + "bool", + "delOldFaces", + "1" + ], + [ + "bool", + "autoFindEdges", + "1" + ], + [ + "bool", + "averagedExtrude", + "1" + ], + [ + "bool", + "flipOldFaces", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimFacesAttrToVerts": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "enum lines tris quads polys", + "faceType", + "tris" + ], + [ + "string", + "faceAttr", + "tmp" + ], + [ + "string", + "vertAttr", + "tmp" + ], + [ + "float", + "deflVal", + "" + ], + [ + "enum sum average min max", + "method", + "average" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimFacesCenterAsVerts": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "enum faces lines", + "faceType", + "faces" + ], + [ + "bool", + "copyFaceAttrs", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimFillAttr": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "string", + "attr", + "rad" + ], + [ + "enum float vec3f int", + "type", + "float" + ], + [ + "float", + "value", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimFillColor": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "vec3f", + "value", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimFilter": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "string", + "tagAttr", + "tag" + ], + [ + "string", + "revampAttrO", + "" + ], + [ + "int", + "tagValue", + "0" + ], + [ + "bool", + "isInversed", + "1" + ], + [ + "enum verts faces", + "method", + "verts" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimFlattenTris": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimFlipFaces": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimFloatAttrToInt": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "string", + "attr", + "tag" + ], + [ + "string", + "attrOut", + "tag" + ], + [ + "float", + "divisor", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimForceTrail": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "PrimitiveObject", + "trailPrim", + "" + ], + [ + "string", + "forceAttr", + "force" + ], + [ + "float", + "attractForce", + "" + ], + [ + "float", + "driftForce", + "" + ], + [ + "", + "attractUDFCurve", + "" + ], + [ + "", + "driftCoordCurve", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimGenerateONB": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "string", + "dirAttr", + "nrm" + ], + [ + "string", + "tanAttrOut", + "tang" + ], + [ + "string", + "bitanAttrOut", + "bitang" + ], + [ + "bool", + "writebackDir", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimGetAttr": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "string", + "name", + "index" + ], + [ + "enum float vec2f vec3f vec4f int vec2i vec3i vec4i", + "type", + "int" + ], + [ + "enum vert tri", + "method", + "tri" + ], + [ + "int", + "index", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "value", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "PrimGetTrisSize": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "int", + "TrisSize", + "0" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "WBTest" + ] + }, + "PrimHasAttr": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "string", + "attrName", + "attr_x" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "hasAttr", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "PrimIntAttrToFloat": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "string", + "attr", + "tag" + ], + [ + "string", + "attrOut", + "tag" + ], + [ + "float", + "divisor", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimKillDeadVerts": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimLineGenerateONB": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "string", + "dirAttrOut", + "dir" + ], + [ + "string", + "tanAttrOut", + "tang" + ], + [ + "string", + "bitanAttrOut", + "bitang" + ], + [ + "bool", + "lineSort", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimLoopUVsToVerts": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimMarkClose": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "float", + "distance", + "" + ], + [ + "string", + "tagAttr", + "weld" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimMarkIndex": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "string", + "tagAttr", + "index" + ], + [ + "enum int float", + "type", + "int" + ], + [ + "int", + "base", + "0" + ], + [ + "int", + "step", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimMarkIsland": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "string", + "tagAttr", + "tag" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimMarkSameIf": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "string", + "tagAttrIn", + "index" + ], + [ + "int", + "tagValueIs", + "0" + ], + [ + "string", + "tagAttrOut", + "weld" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimMarkTrisIdx": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "string", + "idxName", + "index" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "WBTest" + ] + }, + "PrimMatchUVLine": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "prim2", + "" + ], + [ + "string", + "uvAttr", + "tmp" + ], + [ + "string", + "uvAttr2", + "tmp" + ], + [ + "bool", + "copyOtherAttrs", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimMerge": { + "inputs": [ + [ + "list", + "listPrim", + "" + ], + [ + "string", + "tagAttr", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "primitive", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimPerlinNoise": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "string", + "inAttr", + "pos" + ], + [ + "string", + "outAttr", + "tmp" + ], + [ + "float", + "scale", + "" + ], + [ + "float", + "detail", + "" + ], + [ + "float", + "roughness", + "" + ], + [ + "float", + "disortion", + "" + ], + [ + "vec3f", + "offset", + "" + ], + [ + "float", + "average", + "" + ], + [ + "float", + "strength", + "" + ], + [ + "enum float vec3f", + "outType", + "float" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimPointTris": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "int", + "pointID", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "list", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "WBTest" + ] + }, + "PrimProject": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "PrimitiveObject", + "targetPrim", + "" + ], + [ + "string", + "nrmAttr", + "nrm" + ], + [ + "float", + "offset", + "" + ], + [ + "float", + "limit", + "" + ], + [ + "enum front back both", + "allowDir", + "both" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimQuadsLotSubdivision": { + "inputs": [ + [ + "", + "input_quads_model", + "" + ], + [ + "int", + "num", + "1" + ], + [ + "bool", + "row_or_columns", + "0" + ], + [ + "bool", + "random_rc", + "0" + ], + [ + "int", + "random_seed", + "1" + ], + [ + "bool", + "rcrc", + "1" + ], + [ + "bool", + "first_second_same", + "1" + ], + [ + "int", + "same_seed", + "1" + ], + [ + "float", + "min_offset", + "" + ], + [ + "float", + "max_offset", + "" + ], + [ + "float", + "first_edge_minoffset", + "" + ], + [ + "float", + "first_edge_maxoffset", + "" + ], + [ + "int", + "first_seed", + "1" + ], + [ + "float", + "second_edge_minoffset", + "" + ], + [ + "float", + "second_edge_maxoffset", + "" + ], + [ + "int", + "second_seed", + "1" + ], + [ + "bool", + "add_attr", + "0" + ], + [ + "string", + "tag_attr", + "tag" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "output", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimRandomize": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "string", + "attr", + "tmp" + ], + [ + "string", + "dirAttr", + "" + ], + [ + "string", + "seedAttr", + "" + ], + [ + "float", + "base", + "" + ], + [ + "float", + "scale", + "" + ], + [ + "int", + "seed", + "-1" + ], + [ + "enum scalar01 scalar11 cube01 cube11 plane01 plane11 disk cylinder ball semiball sphere semisphere", + "randType", + "scalar01" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimSample": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "sampledObject", + "" + ], + [ + "string", + "srcChannel", + "uv" + ], + [ + "string", + "dstChannel", + "clr" + ], + [ + "float", + "remapMin", + "" + ], + [ + "float", + "remapMax", + "" + ], + [ + "enum REPEAT CLAMP_TO_EDGE CLAMP_TO_BORDER", + "wrap", + "REPEAT" + ], + [ + "vec3f", + "borderColor", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "outPrim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimSample1D": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "heatmap", + "" + ], + [ + "string", + "srcChannel", + "rho" + ], + [ + "string", + "dstChannel", + "clr" + ], + [ + "float", + "remapMin", + "" + ], + [ + "float", + "remapMax", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "outPrim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimSample2D": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "PrimitiveObject", + "image", + "" + ], + [ + "string", + "uvChannel", + "uv" + ], + [ + "enum vertex tris loopsuv", + "uvSource", + "vertex" + ], + [ + "string", + "targetChannel", + "clr" + ], + [ + "float", + "remapMin", + "" + ], + [ + "float", + "remapMax", + "" + ], + [ + "enum REPEAT CLAMP_TO_EDGE CLAMP_TO_BORDER", + "wrap", + "REPEAT" + ], + [ + "enum nearest linear", + "filter", + "nearest" + ], + [ + "vec3f", + "borderColor", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "outPrim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimSample3D": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "vdbGrid", + "" + ], + [ + "string", + "srcChannel", + "pos" + ], + [ + "string", + "dstChannel", + "clr" + ], + [ + "float", + "remapMin", + "" + ], + [ + "float", + "remapMax", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "outPrim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimScale": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "vec3f", + "scale", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimScatter": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "enum tris lines", + "type", + "tris" + ], + [ + "string", + "denAttr", + "" + ], + [ + "float", + "density", + "" + ], + [ + "float", + "minRadius", + "" + ], + [ + "bool", + "interpAttrs", + "1" + ], + [ + "int", + "seed", + "-1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "parsPrim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimSepTriangles": { + "inputs": [ + [ + "primitive", + "prim", + "" + ], + [ + "bool", + "smoothNormal", + "1" + ], + [ + "bool", + "keepTriFaces", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "primitive", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimSetAttr": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "int", + "value", + "0" + ], + [ + "string", + "name", + "index" + ], + [ + "enum float vec2f vec3f vec4f int vec2i vec3i vec4i", + "type", + "int" + ], + [ + "enum vert tri", + "method", + "tri" + ], + [ + "int", + "index", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "PrimSimplifyTag": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "string", + "tagAttr", + "tag" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimSmooth": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimSplit": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimSprayParticles": { + "inputs": [ + [ + "", + "TrianglePrim", + "" + ], + [ + "float", + "Dx", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "particlesPrim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimSuperFormula": { + "inputs": [ + [ + "int", + "segments", + "1000" + ], + [ + "float", + "scale", + "" + ], + [ + "float", + "a", + "" + ], + [ + "float", + "b", + "" + ], + [ + "float", + "m", + "" + ], + [ + "float", + "n1", + "" + ], + [ + "float", + "n2", + "" + ], + [ + "float", + "n3", + "" + ], + [ + "bool", + "hasLines", + "1" + ], + [ + "bool", + "close", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "output", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimToList": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "enum verts points lines tris quads polys loops", + "type", + "verts" + ], + [ + "string", + "attr", + "pos" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "list", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimToVDBPointDataGrid": { + "inputs": [ + [ + "", + "ParticleGeo", + "" + ], + [ + "float", + "Dx", + "" + ], + [ + "", + "vdbPoints", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "Particles", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "PrimTranslate": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "vec3f", + "offset", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimTriPoints": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "int", + "trisID", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "points", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "WBTest" + ] + }, + "PrimTwist": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "vec3f", + "origin", + "" + ], + [ + "vec3f", + "direction", + "" + ], + [ + "", + "tangent", + "" + ], + [ + "float", + "angle", + "" + ], + [ + "float", + "limitMin", + "" + ], + [ + "float", + "limitMax", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimUVEdgeDuplicate": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "bool", + "writeUVToVertex", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimUVVertsToLoopsuv": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimUnmerge": { + "inputs": [ + [ + "primitive", + "prim", + "" + ], + [ + "string", + "tagAttr", + "tag" + ], + [ + "bool", + "preSimplify", + "0" + ], + [ + "enum verts faces", + "method", + "verts" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "list", + "listPrim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimUpdateFromList": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "enum verts points lines tris quads polys loops", + "type", + "verts" + ], + [ + "string", + "attr", + "pos" + ], + [ + "", + "list", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimVertsAttrToFaces": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "enum lines tris quads polys", + "faceType", + "tris" + ], + [ + "string", + "vertAttr", + "tmp" + ], + [ + "string", + "faceAttr", + "tmp" + ], + [ + "enum sum average min max", + "method", + "average" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimWeld": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "string", + "tagAttr", + "weld" + ], + [ + "enum oneof average", + "method", + "oneof" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimWireframe": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "bool", + "removeFaces", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveAddAttr": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "fillValue", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "name", + "clr" + ], + [ + "string", + "pybisgreat", + "DEPRECATED! USE PrimFillAttr INSTEAD" + ], + [ + "enum float float3", + "type", + "float3" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "PrimitiveAttrFit": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "PrimitiveObject", + "refPrim", + "" + ], + [ + "string", + "attrNameSrc", + "pos" + ], + [ + "string", + "attrNameDst", + "pos" + ], + [ + "string", + "refAttrNameSrc", + "pos" + ], + [ + "string", + "refAttrNameDst", + "pos" + ], + [ + "float", + "limitMin", + "" + ], + [ + "float", + "limitMax", + "" + ], + [ + "enum X Y Z", + "axisSrc", + "X" + ], + [ + "enum X Y Z", + "axisDst", + "Y" + ], + [ + "enum X Y Z", + "refAxisSrc", + "X" + ], + [ + "enum X Y Z", + "refAxisDst", + "Y" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "autoMinMax", + "1" + ], + [ + "bool", + "autoSort", + "1" + ] + ], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveAttrPicker": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "enum point line triangle", + "mode", + "point" + ], + [ + "string", + "newAttr", + "" + ], + [ + "float", + "attrVal", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "selected", + "" + ] + ], + "outputs": [ + [ + "", + "list", + "" + ], + [ + "PrimitiveObject", + "outPrim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveBent": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "vec3f", + "origin", + "" + ], + [ + "vec3f", + "tangent", + "" + ], + [ + "vec3f", + "direction", + "" + ], + [ + "float", + "angle", + "" + ], + [ + "float", + "limitMin", + "" + ], + [ + "float", + "limitMax", + "" + ], + [ + "float", + "midPoint", + "" + ], + [ + "float", + "biasDir", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "useOrigin", + "0" + ] + ], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "PrimitiveBinaryOp": { + "inputs": [ + [ + "", + "primA", + "" + ], + [ + "", + "primB", + "" + ], + [ + "", + "primOut", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attrA", + "pos" + ], + [ + "string", + "attrB", + "pos" + ], + [ + "string", + "attrOut", + "pos" + ], + [ + "string", + "op", + "copyA" + ] + ], + "outputs": [ + [ + "", + "primOut", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "PrimitiveBoundingBox": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "float", + "exWidth", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "vec3f", + "bmin", + "" + ], + [ + "vec3f", + "bmax", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveCalcCentroid": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum Volume Area Vertex", + "method", + "Volume" + ] + ], + "outputs": [ + [ + "vec3f", + "centroid", + "" + ], + [ + "float", + "totalArea", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "PrimitiveCalcNormal": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "string", + "nrmAttr", + "nrm" + ], + [ + "bool", + "flip", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveCalcVelocity": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "float", + "dt", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveClearConnect": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "enum edges faces tris quads polys points all", + "type", + "all" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveClip": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "vec3f", + "origin", + "" + ], + [ + "vec3f", + "direction", + "" + ], + [ + "float", + "distance", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "reverse", + "0" + ] + ], + "outputs": [ + [ + "PrimitiveObject", + "outPrim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveColorByHeatmap": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "attrName2", + "" + ], + [ + "", + "heatmap", + "" + ], + [ + "float", + "min", + "" + ], + [ + "float", + "max", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attrName", + "rho" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "visualize" + ] + }, + "PrimitiveCurvemap": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "curvemap", + "" + ], + [ + "string", + "attrName", + "pos" + ], + [ + "int", + "sourceX", + "0" + ], + [ + "int", + "sourceY", + "1" + ], + [ + "int", + "sourceZ", + "2" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveDelAttr": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "name", + "nrm" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveDelAttrs": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "bool", + "invert", + "0" + ], + [ + "string", + "names", + "name_1 name_2" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "PrimitiveDuplicate": { + "inputs": [ + [ + "", + "meshPrim", + "" + ], + [ + "", + "particlesPrim", + "" + ], + [ + "float", + "uniScale", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "attrFromMesh", + "1" + ], + [ + "bool", + "attrFromParticles", + "1" + ], + [ + "string", + "scaleByAttr", + "" + ] + ], + "outputs": [ + [ + "", + "outPrim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "PrimitiveFaceToEdges": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "clearFaces", + "1" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "PrimitiveFarSimpleLines": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveFillAttr": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "NumericObject", + "value", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attrName", + "pos" + ], + [ + "enum float float3 none", + "attrType", + "none" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "PrimitiveFilterByAttr": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "NumericObject", + "value", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum cmpgt cmplt cmpge cmple cmpeq cmpne", + "acceptIf", + "cmpgt" + ], + [ + "string", + "attrName", + "rad" + ], + [ + "bool", + "mockTopos", + "1" + ], + [ + "enum any all", + "vecSelType", + "all" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveFlipPoly": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "primOut", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "PrimitiveGetAttrValue": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "int", + "index", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "name", + "pos" + ], + [ + "enum float float3", + "type", + "float3" + ] + ], + "outputs": [ + [ + "", + "value", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveGetFaceCount": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "size", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveGetSize": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "size", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveHalfBinaryOp": { + "inputs": [ + [ + "", + "primA", + "" + ], + [ + "", + "valueB", + "" + ], + [ + "", + "primOut", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attrA", + "pos" + ], + [ + "string", + "attrOut", + "pos" + ], + [ + "string", + "op", + "copyA" + ] + ], + "outputs": [ + [ + "", + "primOut", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "PrimitiveInterpSubframe": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "float", + "portion", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveLineDistance": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "string", + "resAttr", + "len" + ], + [ + "int", + "start", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveLineSimpleLink": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveLineSolidify": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "int", + "count", + "4" + ], + [ + "float", + "radius", + "" + ], + [ + "string", + "radiusAttr", + "" + ], + [ + "bool", + "isTri", + "1" + ], + [ + "bool", + "sealEnd", + "1" + ], + [ + "bool", + "closeRing", + "0" + ], + [ + "bool", + "lineSort", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveLineSort": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "reversed", + "0" + ] + ], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveMerge": { + "inputs": [ + [ + "", + "listPrim", + "" + ], + [ + "", + "dst", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "PrimitiveMix": { + "inputs": [ + [ + "", + "primA", + "" + ], + [ + "", + "primB", + "" + ], + [ + "", + "primOut", + "" + ], + [ + "", + "coef", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attrA", + "pos" + ], + [ + "string", + "attrB", + "pos" + ], + [ + "string", + "attrOut", + "pos" + ] + ], + "outputs": [ + [ + "", + "primOut", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "PrimitiveNearSimpleLines": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitivePerlinNoiseAttr": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "seed", + "" + ], + [ + "float", + "freq", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attrName", + "noise" + ], + [ + "enum float float3", + "attrType", + "float3" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "noise" + ] + }, + "PrimitivePolygonate": { + "inputs": [ + [ + "primitive", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "with_uv", + "1" + ] + ], + "outputs": [ + [ + "primitive", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitivePrintAttr": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attrName", + "pos" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "PrimitiveRandomAttr": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "NumericObject", + "min", + "" + ], + [ + "NumericObject", + "max", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attrName", + "pos" + ], + [ + "enum float float3", + "attrType", + "" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "PrimitiveRandomizeAttr": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attrName", + "pos" + ], + [ + "enum float float3", + "attrType", + "float3" + ], + [ + "float", + "max", + "" + ], + [ + "float", + "maxY", + "" + ], + [ + "float", + "maxZ", + "" + ], + [ + "float", + "min", + "" + ], + [ + "float", + "minY", + "" + ], + [ + "float", + "minZ", + "" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "PrimitiveReduction": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attr", + "pos" + ], + [ + "enum avg max min absmax", + "op", + "avg" + ] + ], + "outputs": [ + [ + "", + "result", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveResize": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "size", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveScale": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "vec3f", + "origin", + "" + ], + [ + "vec3f", + "axis", + "" + ], + [ + "float", + "scale", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveScatter": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "int", + "npoints", + "100" + ], + [ + "int", + "seed", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum tris lines", + "type", + "tris" + ] + ], + "outputs": [ + [ + "PrimitiveObject", + "points", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveSetAttrValue": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "int", + "index", + "0" + ], + [ + "float", + "value", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "name", + "pos" + ], + [ + "enum float float3", + "type", + "float3" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveSimpleLines": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveSimplePoints": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveSimpleQuads": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveSimpleTris": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveSplitEdges": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "PrimitiveToSDF": { + "inputs": [ + [ + "", + "PrimitiveMesh", + "" + ], + [ + "float", + "Dx", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum vertex cell", + "type", + "vertex" + ] + ], + "outputs": [ + [ + "", + "sdf", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "PrimitiveTraceTrail": { + "inputs": [ + [ + "PrimitiveObject", + "parsPrim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "trailPrim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveTransform": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "enum world bboxCenter", + "pivot", + "world" + ], + [ + "vec3f", + "translation", + "" + ], + [ + "vec3f", + "eulerXYZ", + "" + ], + [ + "vec4f", + "quatRotation", + "" + ], + [ + "vec3f", + "scaling", + "" + ], + [ + "vec3f", + "shear", + "" + ], + [ + "", + "Matrix", + "" + ], + [ + "", + "preTransform", + "" + ], + [ + "", + "local", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "outPrim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveTriangulate": { + "inputs": [ + [ + "primitive", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "from_poly", + "1" + ], + [ + "bool", + "from_quads", + "1" + ], + [ + "bool", + "has_lines", + "1" + ], + [ + "bool", + "with_uv", + "1" + ] + ], + "outputs": [ + [ + "primitive", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "PrimitiveTwist": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "vec3f", + "origin", + "" + ], + [ + "vec3f", + "direction", + "" + ], + [ + "", + "tangent", + "" + ], + [ + "float", + "angle", + "" + ], + [ + "float", + "limitMin", + "" + ], + [ + "float", + "limitMax", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "PrimitiveUnaryOp": { + "inputs": [ + [ + "", + "primA", + "" + ], + [ + "", + "primOut", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attrA", + "pos" + ], + [ + "string", + "attrOut", + "pos" + ], + [ + "string", + "op", + "copy" + ] + ], + "outputs": [ + [ + "", + "primOut", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "PrimitiveWireframe": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "removeFaces", + "1" + ] + ], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "PrintMessage": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "message", + "hello-stdout" + ] + ], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "debug" + ] + }, + "PrintMessageStdErr": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "message", + "hello-stderr" + ] + ], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "debug" + ] + }, + "PrintNumeric": { + "inputs": [ + [ + "NumericObject", + "value", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "hint", + "PrintNumeric" + ] + ], + "outputs": [ + [ + "NumericObject", + "value", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "numeric" + ] + }, + "PrintString": { + "inputs": [ + [ + "string", + "str", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "string" + ] + }, + "ProceduralSky": { + "inputs": [ + [ + "vec2f", + "sunLightDir", + "" + ], + [ + "float", + "sunLightSoftness", + "" + ], + [ + "float", + "sunLightIntensity", + "" + ], + [ + "float", + "colorTemperatureMix", + "" + ], + [ + "float", + "colorTemperature", + "" + ], + [ + "vec2f", + "windDir", + "" + ], + [ + "float", + "timeStart", + "" + ], + [ + "float", + "timeSpeed", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "ProceduralSky", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "ProjectAndNormalize": { + "inputs": [ + [ + "vec3f", + "vec", + "" + ], + [ + "enum XY YX YZ ZY ZX XZ", + "plane", + "XY" + ], + [ + "float", + "directionScale", + "" + ], + [ + "float", + "lengthScale", + "" + ], + [ + "float", + "heightScale", + "" + ], + [ + "float", + "heightOffset", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "vec3f", + "direction", + "" + ], + [ + "float", + "length", + "" + ], + [ + "float", + "height", + "" + ], + [ + "float", + "phase", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "math" + ] + }, + "QuatAngleAxis": { + "inputs": [ + [ + "float", + "angle(D)", + "" + ], + [ + "vec3f", + "axis", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "vec4f", + "quat", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "quat" + ] + }, + "QuatGetAngle": { + "inputs": [ + [ + "vec4f", + "quat", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "float", + "angle(D)", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "quat" + ] + }, + "QuatGetAxis": { + "inputs": [ + [ + "vec4f", + "quat", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "vec3f", + "axis", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "quat" + ] + }, + "QuatRotBetweenVectors": { + "inputs": [ + [ + "vec3f", + "start", + "" + ], + [ + "vec3f", + "dest", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "vec4f", + "quat", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "quat" + ] + }, + "QuatRotate": { + "inputs": [ + [ + "vec4f", + "quat", + "" + ], + [ + "vec3f", + "vec3", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "vec3f", + "vec3", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "quat" + ] + }, + "QueryNearestPrimitive": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "LBvh", + "lbvh", + "" + ], + [ + "string", + "idTag", + "bvh_id" + ], + [ + "string", + "distTag", + "bvh_dist" + ], + [ + "string", + "closestPointTag", + "cp" + ], + [ + "string", + "weightTag", + "bvh_ws" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "NumericObject", + "primid", + "" + ], + [ + "NumericObject", + "bvh_primid", + "" + ], + [ + "NumericObject", + "dist", + "" + ], + [ + "PrimitiveObject", + "bvh_prim", + "" + ], + [ + "PrimitiveObject", + "segment", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "zenofx" + ] + }, + "QueryNearestPrimitiveWithinGroup": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "LBvh", + "lbvh", + "" + ], + [ + "string", + "groupTag", + "island_index" + ], + [ + "string", + "idTag", + "bvh_id" + ], + [ + "string", + "distTag", + "bvh_dist" + ], + [ + "string", + "closestPointTag", + "cp" + ], + [ + "string", + "weightTag", + "bvh_ws" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "NumericObject", + "primid", + "" + ], + [ + "NumericObject", + "bvh_primid", + "" + ], + [ + "NumericObject", + "dist", + "" + ], + [ + "PrimitiveObject", + "bvh_prim", + "" + ], + [ + "PrimitiveObject", + "segment", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "zenofx" + ] + }, + "RadtoDegree": { + "inputs": [ + [ + "float", + "radian", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "float", + "degree", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "math" + ] + }, + "ReadCustomVAT": { + "inputs": [ + [ + "", + "frameid", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "readpath", + "path", + "" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "ReadFBXPrim": { + "inputs": [ + [ + "readpath", + "path", + "" + ], + [ + "readpath", + "hintPath", + "-1" + ], + [ + "bool", + "generate", + "0" + ], + [ + "float", + "offset", + "" + ], + [ + "DictObject", + "visibility", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "indepData", + "0" + ], + [ + "bool", + "primitive", + "0" + ], + [ + "bool", + "printTree", + "0" + ], + [ + "bool", + "triangulate", + "0" + ], + [ + "enum ENABLE DISABLE", + "udim", + "DISABLE" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "data", + "" + ], + [ + "dict", + "datas", + "" + ], + [ + "dict", + "mats", + "" + ], + [ + "", + "animinfo", + "" + ], + [ + "", + "nodetree", + "" + ], + [ + "", + "bonetree", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "FBX" + ] + }, + "ReadImageFile": { + "inputs": [ + [ + "readpath", + "path", + "" + ], + [ + "bool", + "Linearize Non-linear Images", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "image", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "comp" + ] + }, + "ReadLightFromFile": { + "inputs": [ + [ + "readpath", + "path", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "posList", + "" + ], + [ + "", + "rotList", + "" + ], + [ + "", + "sclList", + "" + ], + [ + "", + "colList", + "" + ], + [ + "", + "intList", + "" + ], + [ + "", + "expList", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "FBX" + ] + }, + "ReadObjPrim": { + "inputs": [ + [ + "readpath", + "path", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "triangulate", + "1" + ] + ], + "outputs": [ + [ + "primitive", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "ReadObjPrimitive": { + "inputs": [ + [ + "readpath", + "path", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "ReadObjPrimitiveDict": { + "inputs": [ + [ + "readpath", + "path", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "dict", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "ReadVATFile": { + "inputs": [ + [ + "readpath", + "path", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "image", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "ReadVDB": { + "inputs": [ + [ + "readpath", + "path", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "data", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "ReadVDBGrid": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "readpath", + "path", + "" + ], + [ + "string", + "type", + "" + ] + ], + "outputs": [ + [ + "", + "data", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "RefitPrimitiveBvh": { + "inputs": [ + [ + "LBvh", + "lbvh", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "LBvh", + "lbvh", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "zenofx" + ] + }, + "ResampleVDBGrid": { + "inputs": [ + [ + "", + "resampleTo", + "" + ], + [ + "", + "resampleFrom", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "resampleTo", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "ResizeList": { + "inputs": [ + [ + "", + "list", + "" + ], + [ + "int", + "newSize", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "list", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "list" + ] + }, + "Route": { + "inputs": [ + [ + "", + "input", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "output", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "layout" + ] + }, + "SDFAdvect": { + "inputs": [ + [ + "", + "InoutSDF", + "" + ], + [ + "", + "VecField", + "" + ], + [ + "float", + "TimeStep", + "" + ], + [ + "enum Order_1 Order_2 Order_3 Order_5_WENO Order_5_HJ_WENO", + "SpatialScheme", + "Order_5_HJ_WENO" + ], + [ + "enum Explicit_Euler Order_2_Runge_Kuta Order_3_Runge_Kuta", + "TemporalScheme", + "Order_2_Runge_Kuta" + ], + [ + "int", + "RenormalizeStep", + "3" + ], + [ + "enum Order_1 Order_2 Order_3 Order_5_WENO Order_5_HJ_WENO", + "TrackerSpatialScheme", + "Order_5_HJ_WENO" + ], + [ + "enum Explicit_Euler Order_2_Runge_Kuta Order_3_Runge_Kuta", + "TrackerTemporalScheme", + "Explicit_Euler" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "InoutSDF", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "SDFScatterPoints": { + "inputs": [ + [ + "", + "SDF", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "Points", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "SDFToFog": { + "inputs": [ + [ + "", + "SDF", + "" + ], + [ + "bool", + "inplace", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "oSDF", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "SDFToPoly": { + "inputs": [ + [ + "", + "SDF", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "float", + "adaptivity", + "" + ], + [ + "bool", + "allowQuads", + "0" + ], + [ + "float", + "isoValue", + "" + ] + ], + "outputs": [ + [ + "", + "Mesh", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "SDFToPrim": { + "inputs": [ + [ + "", + "SDF", + "" + ], + [ + "float", + "isoValue", + "" + ], + [ + "float", + "adaptivity", + "" + ], + [ + "bool", + "allowQuads", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "SDFToPrimitive": { + "inputs": [ + [ + "", + "SDF", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "float", + "adaptivity", + "" + ], + [ + "bool", + "allowQuads", + "0" + ], + [ + "float", + "isoValue", + "" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "SampleVDBToPrimitive": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "vdbGrid", + "" + ], + [ + "string", + "sampleBy", + "pos" + ], + [ + "string", + "primAttr", + "sdf" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum Clamp Periodic", + "SampleType", + "Clamp" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "ScalarFieldAnalyzer": { + "inputs": [ + [ + "", + "InVDB", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum Gradient Curvature Laplacian ClosestPoint", + "Operator", + "Gradient" + ] + ], + "outputs": [ + [ + "", + "OutVDB", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "SetFrameTime": { + "inputs": [ + [ + "", + "time", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "frame" + ] + }, + "SetInstancing": { + "inputs": [ + [ + "primitive", + "prim", + "" + ], + [ + "instancing", + "inst", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "primitive", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "SetMaterial": { + "inputs": [ + [ + "primitive", + "prim", + "" + ], + [ + "material", + "mtl", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "primitive", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "SetMatrix": { + "inputs": [ + [ + "", + "dst", + "" + ], + [ + "", + "src", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "math" + ] + }, + "SetPrimInvisible": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "bool", + "invisible", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "out", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "SetRandomSeed": { + "inputs": [ + [ + "", + "routeIn", + "" + ], + [ + "int", + "seed", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "routeOut", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "SetUserData": { + "inputs": [ + [ + "", + "object", + "" + ], + [ + "", + "data", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "key", + "" + ] + ], + "outputs": [ + [ + "", + "object", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "SetUserData2": { + "inputs": [ + [ + "", + "object", + "" + ], + [ + "string", + "key", + "" + ], + [ + "", + "data", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "object", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "lifecycle" + ] + }, + "SetVDBGridClass": { + "inputs": [ + [ + "", + "grid", + "" + ], + [ + "enum UNKNOWN LEVEL_SET FOG_VOLUME STAGGERED", + "VDBGridClass", + "LEVEL_SET" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "grid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "SetVDBGridName": { + "inputs": [ + [ + "", + "grid", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "name", + "density" + ] + ], + "outputs": [ + [ + "", + "grid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "SetVDBPointDataGrid": { + "inputs": [ + [ + "", + "ParticleGeo", + "" + ], + [ + "float", + "Dx", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "float", + "dx", + "" + ] + ], + "outputs": [ + [ + "", + "Particles", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "ShaderBinaryMath": { + "inputs": [ + [ + "float", + "in1", + "" + ], + [ + "float", + "in2", + "" + ], + [ + "enum add sub mul div mod pow atan2 min max dot cross distance safepower", + "op", + "add" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "float", + "out", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "ShaderBlendMode": { + "inputs": [ + [ + "float", + "base", + "" + ], + [ + "float", + "blend", + "" + ], + [ + "float", + "opacity", + "" + ], + [ + "enum add average colorBurn colorDodge darken difference exclusion glow hardLight hardMix lighten linearBurn linearDodge linearLight multiply negation normal overlay phoenix pinLight reflect screen softLight subtract vividLight", + "mode", + "normal" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "shader", + "out", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "ShaderCihouUnrealEngine": { + "inputs": [ + [ + "MaterialObject", + "mtl", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "string", + "code", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "ShaderCustomFunc": { + "inputs": [ + [ + "string", + "args", + "vec3 arg1, vec3 arg2" + ], + [ + "enum float vec2 vec3 vec4", + "rettype", + "vec3" + ], + [ + "string", + "code", + "return arg1 + arg2;" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "ShaderCustomFuncObject", + "func", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "ShaderExtractVec": { + "inputs": [ + [ + "vec3f", + "vec", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "float", + "x", + "" + ], + [ + "float", + "y", + "" + ], + [ + "float", + "z", + "" + ], + [ + "float", + "w", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "ShaderFillVec": { + "inputs": [ + [ + "float", + "in", + "" + ], + [ + "enum float vec2 vec3 vec4", + "type", + "vec3" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "vec4f", + "out", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "ShaderFinalize": { + "inputs": [ + [ + "float", + "base", + "" + ], + [ + "vec3f", + "basecolor", + "" + ], + [ + "float", + "metallic", + "" + ], + [ + "float", + "roughness", + "" + ], + [ + "float", + "specular", + "" + ], + [ + "float", + "subsurface", + "" + ], + [ + "float", + "thickness", + "" + ], + [ + "vec3f", + "sssParam", + "" + ], + [ + "vec3f", + "sssColor", + "" + ], + [ + "float", + "specularTint", + "" + ], + [ + "float", + "anisotropic", + "" + ], + [ + "float", + "anisoRotation", + "" + ], + [ + "float", + "sheen", + "" + ], + [ + "float", + "sheenTint", + "" + ], + [ + "float", + "clearcoat", + "" + ], + [ + "float", + "clearcoatGloss", + "" + ], + [ + "float", + "clearcoatRoughness", + "" + ], + [ + "float", + "clearcoatIOR", + "" + ], + [ + "float", + "specTrans", + "" + ], + [ + "float", + "ior", + "" + ], + [ + "float", + "flatness", + "" + ], + [ + "float", + "scatterDistance", + "" + ], + [ + "float", + "scatterStep", + "" + ], + [ + "float", + "thin", + "" + ], + [ + "float", + "doubleSide", + "" + ], + [ + "vec3f", + "normal", + "" + ], + [ + "float", + "displacement", + "" + ], + [ + "float", + "smoothness", + "" + ], + [ + "float", + "emissionIntensity", + "" + ], + [ + "vec3f", + "emission", + "" + ], + [ + "vec3f", + "reflectance", + "" + ], + [ + "float", + "opacity", + "" + ], + [ + "string", + "commonCode", + "" + ], + [ + "string", + "extensionsCode", + "" + ], + [ + "string", + "mtlid", + "Mat1" + ], + [ + "list", + "tex2dList", + "" + ], + [ + "list", + "tex3dList", + "" + ], + [ + "enum Raw Density Absorption", + "VolumeEmissionScaler", + "Raw" + ], + [ + "float", + "vol_depth", + "" + ], + [ + "float", + "vol_extinction", + "" + ], + [ + "vec3f", + "vol_sample_albedo", + "" + ], + [ + "float", + "vol_sample_anisotropy", + "" + ], + [ + "float", + "vol_sample_density", + "" + ], + [ + "vec3f", + "vol_sample_emission", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum GLSL HLSL", + "backend", + "GLSL" + ] + ], + "outputs": [ + [ + "MaterialObject", + "mtl", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "ShaderHsvAdjust": { + "inputs": [ + [ + "vec3f", + "color", + "" + ], + [ + "vec3f", + "amount", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "out", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "ShaderInputAttr": { + "inputs": [ + [ + "enum pos clr nrm uv tang bitang NoL LoV N T L V H reflectance fresnel instPos instNrm instUv instClr instTang prd.rndf() attrs.localPosLazy() attrs.uniformPosLazy()", + "attr", + "pos" + ], + [ + "enum float vec2 vec3 vec4", + "type", + "vec3" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "shader", + "out", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "ShaderInvokeFunc": { + "inputs": [ + [ + "ShaderCustomFuncObject", + "func", + "" + ], + [ + "list", + "args", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "shader", + "out", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "ShaderLinearFit": { + "inputs": [ + [ + "float", + "in", + "" + ], + [ + "float", + "inMin", + "" + ], + [ + "float", + "inMax", + "" + ], + [ + "float", + "outMin", + "" + ], + [ + "float", + "outMax", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "clamped", + "0" + ] + ], + "outputs": [ + [ + "float", + "out", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "ShaderMakeVec": { + "inputs": [ + [ + "float", + "x", + "" + ], + [ + "float", + "y", + "" + ], + [ + "float", + "z", + "" + ], + [ + "float", + "w", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "vec4f", + "out", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "ShaderNormalMap": { + "inputs": [ + [ + "vec3f", + "normalTexel", + "" + ], + [ + "float", + "scale", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "vec3f", + "out", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "ShaderPackVec": { + "inputs": [ + [ + "shader", + "x", + "" + ], + [ + "shader", + "y", + "" + ], + [ + "shader", + "z", + "" + ], + [ + "shader", + "w", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "vec4f", + "out", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "ShaderPackVector": { + "inputs": [ + [ + "float", + "x", + "" + ], + [ + "float", + "y", + "" + ], + [ + "float", + "z", + "" + ], + [ + "float", + "w", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum float vec2 vec3 vec4", + "type", + "vec3" + ] + ], + "outputs": [ + [ + "", + "out", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "ShaderReduceVec": { + "inputs": [ + [ + "vec3f", + "in", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum average sum", + "op", + "average" + ] + ], + "outputs": [ + [ + "float", + "out", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "ShaderTernaryMath": { + "inputs": [ + [ + "float", + "in1", + "" + ], + [ + "float", + "in2", + "" + ], + [ + "float", + "in3", + "" + ], + [ + "enum mix clamp smoothstep add3", + "op", + "mix" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "float", + "out", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "ShaderTexture2D": { + "inputs": [ + [ + "int", + "texId", + "0" + ], + [ + "", + "coord", + "" + ], + [ + "vec2f", + "uvtiling", + "" + ], + [ + "enum float vec2 vec3 vec4", + "type", + "vec3" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "shader", + "out", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "ShaderTexture3D": { + "inputs": [ + [ + "int", + "texId", + "0" + ], + [ + "vec3f", + "coord", + "" + ], + [ + "enum World Local", + "space", + "World" + ], + [ + "enum vec2", + "type", + "vec2" + ], + [ + "enum Closest Trilinear Triquadratic Tricubic Stochastic", + "method", + "Trilinear" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "shader", + "out", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "ShaderUnaryMath": { + "inputs": [ + [ + "float", + "in1", + "" + ], + [ + "enum copy neg abs sqrt inversesqrt exp log sin cos tan asin acos atan degrees radians sinh cosh tanh asinh acosh atanh round roundEven floor ceil trunc sign step length normalize hsvToRgb rgbToHsv luminance", + "op", + "sqrt" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "float", + "out", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "ShaderUniformAttr": { + "inputs": [ + [ + "int", + "idx", + "0" + ], + [ + "enum float vec2 vec3 vec4", + "type", + "vec3" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "shader", + "out", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "ShaderVecConvert": { + "inputs": [ + [ + "float", + "in", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum vec2 vec3 vec4", + "type", + "vec3" + ] + ], + "outputs": [ + [ + "", + "out", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "SpdlogErrorMessage": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "message", + "error from spdlog!" + ] + ], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "debug" + ] + }, + "SpdlogInfoMessage": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "message", + "hello from spdlog!" + ] + ], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "debug" + ] + }, + "StringEqual": { + "inputs": [ + [ + "string", + "lhs", + "" + ], + [ + "string", + "rhs", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "bool", + "isEqual", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "string" + ] + }, + "StringEval": { + "inputs": [ + [ + "string", + "zfxCode", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "string", + "result", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "zenofx" + ] + }, + "StringFormat": { + "inputs": [ + [ + "string", + "str", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "string", + "str", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "StringFormatNumStr": { + "inputs": [ + [ + "string", + "str", + "{}" + ], + [ + "", + "num_str", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "string", + "str", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "string" + ] + }, + "StringFormatNumber": { + "inputs": [ + [ + "string", + "str", + "{}" + ], + [ + "", + "number", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "string", + "str", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "StringToList": { + "inputs": [ + [ + "string", + "string", + "" + ], + [ + "string", + "Separator", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "list", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "string" + ] + }, + "StringToNumber": { + "inputs": [ + [ + "enum float int", + "type", + "all" + ], + [ + "string", + "str", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "num_str", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "string" + ] + }, + "SubCategory": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "name", + "subgraph" + ] + ], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "subgraph" + ] + }, + "SubInput": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "defl", + "" + ], + [ + "string", + "name", + "input1" + ], + [ + "string", + "type", + "" + ] + ], + "outputs": [ + [ + "", + "port", + "" + ], + [ + "bool", + "hasValue", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "subgraph" + ] + }, + "SubLine": { + "inputs": [ + [ + "", + "line", + "" + ], + [ + "NumericObject", + "value", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum cmpgt cmplt cmpge cmple cmpeq cmpne", + "acceptIf", + "cmpgt" + ], + [ + "string", + "attrName", + "rad" + ], + [ + "enum any all", + "vecSelType", + "all" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "SubOutput": { + "inputs": [ + [ + "", + "port", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "defl", + "" + ], + [ + "string", + "name", + "output1" + ], + [ + "string", + "type", + "" + ] + ], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "subgraph" + ] + }, + "SubstepDt": { + "inputs": [ + [ + "", + "FOR", + "" + ], + [ + "float", + "desired_dt", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "float", + "actual_dt", + "" + ], + [ + "float", + "portion", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "control" + ] + }, + "SyncPrimitiveAttributes": { + "inputs": [ + [ + "", + "prim1", + "" + ], + [ + "", + "prim2", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim1", + "" + ], + [ + "", + "prim2", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "TargetCamera": { + "inputs": [ + [ + "vec3f", + "pos", + "" + ], + [ + "vec3f", + "refUp", + "" + ], + [ + "vec3f", + "target", + "" + ], + [ + "float", + "near", + "" + ], + [ + "float", + "far", + "" + ], + [ + "float", + "fov", + "" + ], + [ + "float", + "aperture", + "" + ], + [ + "float", + "focalPlaneDistance", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "CameraObject", + "camera", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "shader" + ] + }, + "TestRayBox": { + "inputs": [ + [ + "", + "ray_origin", + "" + ], + [ + "", + "ray_dir", + "" + ], + [ + "", + "box_min", + "" + ], + [ + "", + "box_max", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "predicate", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "ToView": { + "inputs": [ + [ + "", + "object", + "" + ], + [ + "bool", + "isStatic", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "object", + "" + ], + [ + "string", + "viewid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "layout" + ] + }, + "TraceOneStep": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "dt", + "" + ], + [ + "", + "size", + "" + ], + [ + "", + "steps", + "" + ], + [ + "", + "maxlength", + "" + ], + [ + "", + "vecField", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "TracePositionOneStep": { + "inputs": [ + [ + "", + "primData", + "" + ], + [ + "", + "primStart", + "" + ], + [ + "string", + "lineTag", + "lineID" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "primVis", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "visualize" + ] + }, + "TransformPrimitive": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "vec3f", + "translation", + "" + ], + [ + "vec3f", + "eulerXYZ", + "" + ], + [ + "vec4f", + "quatRotation", + "" + ], + [ + "vec3f", + "scaling", + "" + ], + [ + "vec3f", + "shear", + "" + ], + [ + "", + "Matrix", + "" + ], + [ + "", + "preTransform", + "" + ], + [ + "", + "local", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "outPrim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "TransformVDB": { + "inputs": [ + [ + "", + "VDBGrid", + "" + ], + [ + "vec3f", + "translation", + "" + ], + [ + "vec3f", + "eulerXYZ", + "" + ], + [ + "vec3f", + "scaling", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "VDBGrid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "TrianglesWrangle": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "string", + "zfxCode", + "" + ], + [ + "DictObject:NumericObject", + "params", + "" + ], + [ + "enum points lines tris quads loops polys", + "faceType", + "tris" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "zenofx" + ] + }, + "TriggerAbortSignal": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "debug" + ] + }, + "TriggerDivideZero": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "debug" + ] + }, + "TriggerException": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "message", + "exception occurred!" + ] + ], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "debug" + ] + }, + "TriggerExitProcess": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "int", + "status", + "-1" + ] + ], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "debug" + ] + }, + "TriggerSegFault": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "debug" + ] + }, + "TriggerViewportFault": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "debug" + ] + }, + "UVProjectFromPlane": { + "inputs": [ + [ + "PrimitiveObject", + "prim", + "" + ], + [ + "PrimitiveObject", + "refPlane", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "PrimitiveObject", + "outPrim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "UnpackNumericVec": { + "inputs": [ + [ + "vec3f", + "vec", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "float", + "X", + "" + ], + [ + "float", + "Y", + "" + ], + [ + "float", + "Z", + "" + ], + [ + "float", + "W", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "numeric" + ] + }, + "UpdateCurveControlPoint": { + "inputs": [ + [ + "curve", + "curve", + "" + ], + [ + "string", + "key", + "x" + ], + [ + "int", + "index", + "0" + ], + [ + "optional float", + "point_x", + "" + ], + [ + "optional float", + "point_y", + "" + ], + [ + "optional vec2f", + "left_handler", + "" + ], + [ + "optional vec2f", + "right_handler", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "curve", + "curve", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "curve" + ] + }, + "UpdateCurveCycleType": { + "inputs": [ + [ + "curve", + "curve", + "" + ], + [ + "string", + "key", + "x" + ], + [ + "enum CLAMP CYCLE MIRROR", + "type", + "CLAMP" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "curve", + "curve", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "curve" + ] + }, + "UpdateCurveXYRange": { + "inputs": [ + [ + "curve", + "curve", + "" + ], + [ + "string", + "key", + "x" + ], + [ + "optional float", + "x_from", + "" + ], + [ + "optional float", + "x_to", + "" + ], + [ + "optional float", + "y_from", + "" + ], + [ + "optional float", + "y_to", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "curve", + "curve", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "curve" + ] + }, + "VDBAddPerlinNoise": { + "inputs": [ + [ + "", + "inoutSDF", + "" + ], + [ + "float", + "strength", + "" + ], + [ + "float", + "scale", + "" + ], + [ + "vec3f", + "scaling", + "" + ], + [ + "vec3f", + "translation", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "inoutSDF", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "VDBAddTurbulentNoise": { + "inputs": [ + [ + "", + "inoutSDF", + "" + ], + [ + "float", + "strength", + "" + ], + [ + "float", + "scale", + "" + ], + [ + "vec3f", + "scaling", + "" + ], + [ + "vec3f", + "translation", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "inoutSDF", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "VDBChangeBackground": { + "inputs": [ + [ + "", + "grid", + "" + ], + [ + "float", + "background", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "grid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "VDBCreateLevelsetSphere": { + "inputs": [ + [ + "float", + "Dx", + "" + ], + [ + "float", + "radius", + "" + ], + [ + "vec3f", + "center", + "" + ], + [ + "float", + "half_width", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "data", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "VDBDeactivate": { + "inputs": [ + [ + "", + "Field", + "" + ], + [ + "", + "Mask", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "VDBDilateTopo": { + "inputs": [ + [ + "", + "inField", + "" + ], + [ + "int", + "layers", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "oField", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "VDBErodeSDF": { + "inputs": [ + [ + "", + "inoutSDF", + "" + ], + [ + "float", + "depth", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "inoutSDF", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "VDBExplosiveTurbulentNoise": { + "inputs": [ + [ + "", + "inoutSDF", + "" + ], + [ + "float", + "strength", + "" + ], + [ + "float", + "scale", + "" + ], + [ + "vec3f", + "scaling", + "" + ], + [ + "vec3f", + "translation", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "float", + "FBM_EvalPersist", + "" + ], + [ + "float", + "FBM_Lacunarity", + "" + ], + [ + "int", + "FBM_Octaves", + "5" + ], + [ + "float", + "FBM_Persistence", + "" + ], + [ + "float", + "FBM_WarpPersist", + "" + ], + [ + "float", + "FBM_WarpPrimary", + "" + ], + [ + "float", + "FBM_WarpSecond", + "" + ], + [ + "float", + "Speed", + "" + ], + [ + "float", + "UVScale", + "" + ] + ], + "outputs": [ + [ + "", + "inoutSDF", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "VDBFillActiveVoxels": { + "inputs": [ + [ + "", + "grid", + "" + ], + [ + "NumericObject", + "fillValue", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "grid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "VDBGetBackground": { + "inputs": [ + [ + "", + "grid", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "float", + "background", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "VDBInvertSDF": { + "inputs": [ + [ + "", + "grid", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "grid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "VDBLeafAsParticles": { + "inputs": [ + [ + "", + "vdbGrid", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "primPars", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "visualize" + ] + }, + "VDBPerlinNoise": { + "inputs": [ + [ + "", + "inoutSDF", + "" + ], + [ + "float", + "scale", + "" + ], + [ + "vec3f", + "scale3d", + "" + ], + [ + "float", + "detail", + "" + ], + [ + "float", + "roughness", + "" + ], + [ + "float", + "disortion", + "" + ], + [ + "vec3f", + "offset", + "" + ], + [ + "float", + "average", + "" + ], + [ + "float", + "strength", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "inoutSDF", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "VDBPointScatter": { + "inputs": [ + [ + "", + "grid", + "" + ], + [ + "int", + "count", + "4" + ], + [ + "float", + "spread", + "" + ], + [ + "int", + "seed", + "-1" + ], + [ + "enum Fog SDF", + "gridtype", + "Fog" + ], + [ + "enum PerVoxel Total", + "counttype", + "PerVoxel" + ], + [ + "enum Uniform NonUniform", + "method", + "Uniform" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "points", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "VDBPointsToPrimitive": { + "inputs": [ + [ + "", + "grid", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "VDBPruneFootprint": { + "inputs": [ + [ + "", + "grid", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "grid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "VDBRenormalizeSDF": { + "inputs": [ + [ + "", + "inoutSDF", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "int", + "dilateIters", + "0" + ], + [ + "int", + "iterations", + "4" + ], + [ + "enum 1oUpwind", + "method", + "1oUpwind" + ] + ], + "outputs": [ + [ + "", + "inoutSDF", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "VDBSmooth": { + "inputs": [ + [ + "", + "inoutVDB", + "" + ], + [ + "", + "MaskGrid", + "" + ], + [ + "enum Mean Gaussian Median", + "type", + "Gaussian" + ], + [ + "int", + "width", + "1" + ], + [ + "int", + "iterations", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "inoutVDB", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "VDBSmoothSDF": { + "inputs": [ + [ + "", + "inoutSDF", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "DEPRECATED", + "Use VDBSmooth Instead" + ], + [ + "int", + "iterations", + "1" + ], + [ + "int", + "width", + "1" + ] + ], + "outputs": [ + [ + "", + "inoutSDF", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "VDBTopoCopy": { + "inputs": [ + [ + "", + "grid", + "" + ], + [ + "", + "topo", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "grid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "VDBTouchAABBRegion": { + "inputs": [ + [ + "", + "grid", + "" + ], + [ + "vec3f", + "bmin", + "" + ], + [ + "vec3f", + "bmax", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "grid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "VDBVoxelAsParticles": { + "inputs": [ + [ + "", + "vdbGrid", + "" + ], + [ + "string", + "valToAttr", + "sdf" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "asStaggers", + "1" + ], + [ + "bool", + "hasInactive", + "0" + ] + ], + "outputs": [ + [ + "", + "primPars", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "visualize" + ] + }, + "VDBWrangle": { + "inputs": [ + [ + "VDBGrid", + "grid", + "" + ], + [ + "string", + "zfxCode", + "" + ], + [ + "enum true false", + "ModifyActive", + "false" + ], + [ + "enum true false", + "ChangeBackground", + "false" + ], + [ + "DictObject:NumericObject", + "params", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "VDBGrid", + "grid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "zenofx" + ] + }, + "VectorFieldAnalyzer": { + "inputs": [ + [ + "", + "InVDB", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "enum Divergence Curl Magnitude Normalize", + "Operator", + "Divergence" + ] + ], + "outputs": [ + [ + "", + "OutVDB", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "VisPrimAttrValue_Modify": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "string", + "attrName", + "pos" + ], + [ + "float", + "scale", + "" + ], + [ + "int", + "precision", + "3" + ], + [ + "bool", + "includeSelf", + "0" + ], + [ + "bool", + "dotDecoration", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "outPrim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "WBTest" + ] + }, + "VisVec3Attribute": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "string", + "name", + "vel" + ], + [ + "bool", + "normalize", + "1" + ], + [ + "float", + "lengthScale", + "" + ], + [ + "vec3f", + "color", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "primVis", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "visualize" + ] + }, + "VolumeAdvect": { + "inputs": [ + [ + "", + "InField", + "" + ], + [ + "", + "VecField", + "" + ], + [ + "float", + "TimeStep", + "" + ], + [ + "int", + "SubSteps", + "1" + ], + [ + "enum SemiLagrangian MidPoint RK3 RK4 MacCormack BFECC", + "Integrator", + "BFECC" + ], + [ + "enum None Clamp Revert", + "Limiter", + "Revert" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "extend", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "WBPrimBend": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "int", + "Limit Deformation", + "1" + ], + [ + "int", + "Symmetric Deformation", + "0" + ], + [ + "float", + "Bend Angle (degree)", + "" + ], + [ + "vec3f", + "Up Vector", + "" + ], + [ + "vec3f", + "Capture Origin", + "" + ], + [ + "vec3f", + "Capture Direction", + "" + ], + [ + "float", + "Capture Length", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "WebAsset": { + "inputs": [ + [ + "string", + "url", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "WorkPath", + "$ZSG" + ], + [ + "string", + "action", + "unzip" + ], + [ + "enum Curl Wget Aria2", + "method", + "Curl" + ] + ], + "outputs": [ + [ + "string", + "path", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "string" + ] + }, + "WriteCustomVAT": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "frameid", + "" + ], + [ + "bool", + "UnrealEngine", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "int", + "frameEnd", + "100" + ], + [ + "int", + "frameStart", + "0" + ], + [ + "writepath", + "path", + "" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "WriteImageFile": { + "inputs": [ + [ + "", + "image", + "" + ], + [ + "writepath", + "path", + "" + ], + [ + "enum png jpg exr pfm", + "type", + "png" + ], + [ + "", + "mask", + "" + ], + [ + "bool", + "gamma", + "1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "image", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "comp" + ] + }, + "WriteObjPrim": { + "inputs": [ + [ + "primitive", + "prim", + "" + ], + [ + "writepath", + "path", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "bool", + "polygonate", + "1" + ] + ], + "outputs": [ + [ + "primitive", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "WriteObjPrimitive": { + "inputs": [ + [ + "writepath", + "path", + "" + ], + [ + "", + "prim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "WritePrimToCSV": { + "inputs": [ + [ + "primitive", + "prim", + "" + ], + [ + "writepath", + "path", + "" + ], + [ + "enum verts points lines tris quads loops polys", + "type", + "verts" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "primitive", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "primitive" + ] + }, + "WriteVDB": { + "inputs": [ + [ + "", + "data", + "" + ], + [ + "writepath", + "path", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "openvdb" + ] + }, + "WriteVDBGrid": { + "inputs": [ + [ + "", + "data", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "writepath", + "path", + "" + ] + ], + "outputs": [ + [ + "", + "DST", + "" + ] + ], + "categories": [ + "deprecated" + ] + }, + "ZipListAsDict": { + "inputs": [ + [ + "ListObject", + "keys", + "" + ], + [ + "ListObject", + "values", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "DictObject", + "dict", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "dict" + ] + }, + "erode_domainWarping_v1": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "float", + "fbmH", + "" + ], + [ + "float", + "fbmFrequence", + "" + ], + [ + "float", + "fbmAmplitude", + "" + ], + [ + "int", + "fbmNumOctaves", + "4" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attrName", + "noise" + ], + [ + "enum float float3", + "attrType", + "float" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "erode_domainWarping_v2": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "float", + "fbmH", + "" + ], + [ + "float", + "fbmFrequence", + "" + ], + [ + "float", + "fbmAmplitude", + "" + ], + [ + "int", + "fbmNumOctaves", + "4" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attrName", + "noise" + ], + [ + "enum float float3", + "attrType", + "float" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "erode_hybridMultifractal_v1": { + "inputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "float", + "H", + "" + ], + [ + "float", + "lacunarity", + "" + ], + [ + "float", + "octaves", + "" + ], + [ + "float", + "offset", + "" + ], + [ + "float", + "scale", + "" + ], + [ + "float", + "persistence", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attrName", + "hybrid" + ], + [ + "enum float float3", + "attrType", + "float" + ] + ], + "outputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "erode_hybridMultifractal_v2": { + "inputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "float", + "H", + "" + ], + [ + "float", + "lacunarity", + "" + ], + [ + "float", + "octaves", + "" + ], + [ + "float", + "offset", + "" + ], + [ + "float", + "scale", + "" + ], + [ + "float", + "persistence", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attrName", + "hybrid" + ], + [ + "enum float float3", + "attrType", + "float" + ] + ], + "outputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "erode_hybridMultifractal_v3": { + "inputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "float", + "H", + "" + ], + [ + "float", + "lacunarity", + "" + ], + [ + "float", + "octaves", + "" + ], + [ + "float", + "offset", + "" + ], + [ + "float", + "scale", + "" + ], + [ + "float", + "persistence", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attrName", + "hybrid" + ], + [ + "enum float float3", + "attrType", + "float" + ] + ], + "outputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "erode_noise_analytic_simplex_2d": { + "inputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "string", + "posLikeAttrName", + "pos" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attrName", + "analyticNoise" + ] + ], + "outputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "erode_noise_perlin": { + "inputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "string", + "vec3fAttrName", + "pos" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attrName", + "noise" + ], + [ + "enum float float3", + "attrType", + "float" + ] + ], + "outputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "erode_noise_simplex": { + "inputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "string", + "posLikeAttrName", + "pos" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attrName", + "noise" + ], + [ + "enum float float3", + "attrType", + "float" + ] + ], + "outputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "erode_noise_sparse_convolution": { + "inputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "string", + "posLikeAttrName", + "pos" + ], + [ + "int", + "pulsenum", + "3" + ], + [ + "int", + "griddist", + "2" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attrName", + "noise" + ], + [ + "enum float float3", + "attrType", + "float" + ] + ], + "outputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "erode_noise_worley": { + "inputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "vec3f", + "seed", + "" + ], + [ + "string", + "posLikeAttrName", + "pos" + ], + [ + "float", + "celljitter", + "" + ], + [ + "enum Euclidean Chebyshev Manhattan", + "distType", + "Euclidean" + ], + [ + "enum F1 F2-F1", + "fType", + "F1" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attrName", + "noise" + ], + [ + "enum float float3", + "attrType", + "float" + ] + ], + "outputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "erode_rand_color": { + "inputs": [ + [ + "int", + "iterations", + "0" + ], + [ + "int", + "iter", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "list", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "erode_rand_dir": { + "inputs": [ + [ + "int", + "iterations", + "0" + ], + [ + "int", + "iter", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "list", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "erode_smooth_flow": { + "inputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "float", + "smoothRate", + "" + ], + [ + "string", + "flowName", + "flow" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "erode_terrainHiMeLo": { + "inputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "string", + "attrName", + "fbm" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "erode_tumble_material_erosion": { + "inputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "ListObject", + "perm", + "" + ], + [ + "ListObject", + "p_dirs", + "" + ], + [ + "ListObject", + "x_dirs", + "" + ], + [ + "float", + "seed", + "" + ], + [ + "int", + "iterations", + "0" + ], + [ + "int", + "iter", + "0" + ], + [ + "int", + "i", + "0" + ], + [ + "int", + "openborder", + "0" + ], + [ + "float", + "maxdepth", + "" + ], + [ + "float", + "global_erosionrate", + "" + ], + [ + "float", + "erosionrate", + "" + ], + [ + "float", + "cutangle", + "" + ], + [ + "string", + "cutangle_mask_layer", + "cutangle_mask" + ], + [ + "float", + "erodability", + "" + ], + [ + "string", + "erodability_mask_layer", + "erodability_mask" + ], + [ + "float", + "removalrate", + "" + ], + [ + "string", + "removalrate_mask_layer", + "removalrate_mask" + ], + [ + "float", + "gridbias", + "" + ], + [ + "string", + "gridbias_mask_layer", + "gridbias_mask" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "erode_tumble_material_v0": { + "inputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "ListObject", + "perm", + "" + ], + [ + "ListObject", + "p_dirs", + "" + ], + [ + "ListObject", + "x_dirs", + "" + ], + [ + "float", + "seed", + "" + ], + [ + "int", + "iterations", + "0" + ], + [ + "int", + "iter", + "0" + ], + [ + "int", + "i", + "0" + ], + [ + "int", + "openborder", + "0" + ], + [ + "float", + "maxdepth", + "" + ], + [ + "float", + "global_erosionrate", + "" + ], + [ + "float", + "erosionrate", + "" + ], + [ + "float", + "cutangle", + "" + ], + [ + "string", + "cutangle_mask_layer", + "cutangle_mask" + ], + [ + "float", + "erodability", + "" + ], + [ + "string", + "erodability_mask_layer", + "erodability_mask" + ], + [ + "float", + "removalrate", + "" + ], + [ + "string", + "removalrate_mask_layer", + "removalrate_mask" + ], + [ + "float", + "gridbias", + "" + ], + [ + "string", + "gridbias_mask_layer", + "gridbias_mask" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "erode_tumble_material_v1": { + "inputs": [ + [ + "", + "HeightField", + "" + ], + [ + "string", + "write_back_material_layer", + "write_back_material" + ], + [ + "int", + "openborder", + "0" + ], + [ + "float", + "repose_angle", + "" + ], + [ + "float", + "flow_rate", + "" + ], + [ + "float", + "height_factor", + "" + ], + [ + "float", + "entrainmentrate", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "HeightField", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "erode_tumble_material_v2": { + "inputs": [ + [ + "", + "HeightField", + "" + ], + [ + "string", + "stabilitymask", + "_stability" + ], + [ + "ListObject", + "perm", + "" + ], + [ + "ListObject", + "p_dirs", + "" + ], + [ + "ListObject", + "x_dirs", + "" + ], + [ + "float", + "seed", + "" + ], + [ + "int", + "iterations", + "0" + ], + [ + "int", + "iter", + "0" + ], + [ + "int", + "i", + "0" + ], + [ + "int", + "openborder", + "0" + ], + [ + "float", + "gridbias", + "" + ], + [ + "float", + "repose_angle", + "" + ], + [ + "float", + "quant_amt", + "" + ], + [ + "float", + "flow_rate", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "HeightField", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "erode_tumble_material_v3": { + "inputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "string", + "stabilitymask", + "_stability" + ], + [ + "ListObject", + "perm", + "" + ], + [ + "ListObject", + "p_dirs", + "" + ], + [ + "ListObject", + "x_dirs", + "" + ], + [ + "float", + "seed", + "" + ], + [ + "int", + "iterations", + "0" + ], + [ + "int", + "iter", + "0" + ], + [ + "int", + "i", + "0" + ], + [ + "int", + "openborder", + "0" + ], + [ + "float", + "gridbias", + "" + ], + [ + "float", + "repose_angle", + "" + ], + [ + "float", + "quant_amt", + "" + ], + [ + "float", + "flow_rate", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "erode_tumble_material_v4": { + "inputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "ListObject", + "perm", + "" + ], + [ + "ListObject", + "p_dirs", + "" + ], + [ + "ListObject", + "x_dirs", + "" + ], + [ + "float", + "seed", + "" + ], + [ + "int", + "iterations", + "40" + ], + [ + "int", + "iter", + "0" + ], + [ + "int", + "i", + "0" + ], + [ + "int", + "openborder", + "0" + ], + [ + "float", + "gridbias", + "" + ], + [ + "float", + "global_erosionrate", + "" + ], + [ + "float", + "erodability", + "" + ], + [ + "float", + "erosionrate", + "" + ], + [ + "float", + "bank_angle", + "" + ], + [ + "float", + "removalrate", + "" + ], + [ + "float", + "max_debris_depth", + "" + ], + [ + "int", + "max_erodability_iteration", + "5" + ], + [ + "float", + "initial_erodability_factor", + "" + ], + [ + "float", + "slope_contribution_factor", + "" + ], + [ + "float", + "bed_erosionrate_factor", + "" + ], + [ + "float", + "depositionrate", + "" + ], + [ + "float", + "sedimentcap", + "" + ], + [ + "float", + "bank_erosionrate_factor", + "" + ], + [ + "float", + "max_bank_bed_ratio", + "" + ], + [ + "float", + "quant_amt", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "erode_value2cond": { + "inputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "float", + "value", + "" + ], + [ + "float", + "seed", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim_2DGrid", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "erode_voronoi": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "featurePrim", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [ + [ + "string", + "attrName", + "voronoi" + ] + ], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "erode" + ] + }, + "str2num": { + "inputs": [ + [ + "enum float int", + "type", + "int" + ], + [ + "string", + "str", + "0" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "num", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "WBTest" + ] + }, + "testPoly1": { + "inputs": [ + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "WBTest" + ] + }, + "testPoly2": { + "inputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "list", + "" + ], + [ + "", + "SRC", + "" + ] + ], + "params": [], + "outputs": [ + [ + "", + "prim", + "" + ], + [ + "", + "DST", + "" + ] + ], + "categories": [ + "WBTest" + ] + } + }, + "version": "v2.5" +} \ No newline at end of file diff --git a/projects/CuLagrange/CMakeLists.txt b/projects/CuLagrange/CMakeLists.txt index f539068361..fa05caca3f 100644 --- a/projects/CuLagrange/CMakeLists.txt +++ b/projects/CuLagrange/CMakeLists.txt @@ -35,8 +35,10 @@ target_sources(zeno PRIVATE # pbd target_sources(zeno PRIVATE - pbd/PBDInit.cu - pbd/PBDPipeline.cu + pbd/Constraints.cu + pbd/SelfCollision.cu + pbd/KinematicCollision.cu + # pbd/Pipeline.cu ) # fem-cloth diff --git a/projects/CuLagrange/fem/FleshDynamicStepping.cu b/projects/CuLagrange/fem/FleshDynamicStepping.cu index df1f50a378..62558f2dda 100644 --- a/projects/CuLagrange/fem/FleshDynamicStepping.cu +++ b/projects/CuLagrange/fem/FleshDynamicStepping.cu @@ -681,7 +681,7 @@ struct FleshDynamicStepping : INode { dt = dt,offset = offset] ZS_LAMBDA(int ei) mutable { auto m = eles("m",ei)/(T)4.0; auto inds = eles.pack(dim_c<4>,"inds",ei).reinterpret_bits(int_c); - auto pgrad = zs::vec::zeros(); + // auto pgrad = zs::vec::zeros(); // auto H = zs::vec::zeros(); // if(eles.hasProperty("dt")) { // dt2 = eles("dt",ei) * eles("dt",ei); @@ -701,8 +701,13 @@ struct FleshDynamicStepping : INode { auto x0 = vtemp.pack(dim_c<3>,"xp",inds[i]); auto v0 = vtemp.pack(dim_c<3>,"vp",inds[i]); - auto alpha = inertia * m/dt2 * A; + auto alpha = (inertia * m / dt2) * A; auto nodal_pgrad = -alpha * (x1 - x0 - v0 * dt); + + if(isnan(nodal_pgrad.norm())) { + printf("nan nodal pgrad detected : %f %f %f %f\n",(float)alpha.norm(),(float)x1.norm(),(float)x0.norm(),(float)v0.norm()); + } + for(int d = 0;d != 3;++d){ auto idx = i * 3 + d; gh_buffer("grad",idx,ei + offset) = nodal_pgrad[d]; @@ -719,6 +724,9 @@ struct FleshDynamicStepping : INode { }); } + // auto gradn_after_inertia = TILEVEC_OPS::dot<12>(cudaPol,gh_buffer,"grad","grad"); + // std::cout << "gradn_after_inertia : " << gradn_after_inertia << std::endl; + cudaPol(zs::range(eles.size()), [dt = dt,dt2 = dt2,aniso_strength = aniso_strength, verts = proxy({},verts), vtemp = proxy({}, vtemp), @@ -767,6 +775,7 @@ struct FleshDynamicStepping : INode { auto dFdXT = dFdX.transpose(); auto vf = -vole * (dFdXT * vecP); + auto mg = volf * vole / (T)4.0; for(int i = 0;i != 4;++i) for(int d = 0;d !=3 ;++d){ @@ -784,25 +793,34 @@ struct FleshDynamicStepping : INode { auto fiber = eles.pack(dim_c<3>,"fiber",ei); if(zs::abs(fiber.norm() - 1.0) < 1e-3) { fiber /= fiber.norm(); - // if(eles.hasProperty("mu")) { - // amodel.mu = eles("mu",ei); - // // amodel.lam = eles("lam",ei); + if(eles.hasProperty("mu") && eles.hasProperty("lam")) { + amodel.mu = eles("mu",ei); + // amodel.lam = eles("lam",ei); - // } + } + // COMMIT FIND A ANISOTROPIC BUG HERE auto aP = amodel.do_first_piola(FAct,fiber); - auto vecAP = flatten(P); - vecAP = dFActdF.transpose() * vecP; + auto vecAP = flatten(aP); + vecAP = dFActdF.transpose() * vecAP; vf -= vole * dFdXT * vecAP *aniso_strength; - // auto aHq = amodel.do_first_piola_derivative(FAct,fiber); - auto aHq = zs::vec::zeros(); + auto aHq = amodel.do_first_piola_derivative(FAct,fiber); + // auto aHq = zs::vec::zeros(); H += dFdAct_dFdX.transpose() * aHq * dFdAct_dFdX * vole * aniso_strength; // if((int)eles("Muscle_ID",ei) == 0){ // printf("fiber : %f %f %f,Fa = %f,aP = %f,aHq = %f,H = %f\n",fiber[0],fiber[1],fiber[2],(float)FAct.norm(),(float)aP.norm(),(float)aHq.norm(),(float)H.norm()); // } + + if(isnan(vf.norm())) { + printf("nan nodal aniso_vf detected : %f %f %f %f\n",(float)vecP.norm(),(float)volf.norm(),(float)vecAP.norm(),(float)aHq.norm()); + } } } + // if(isnan(vf.norm())) { + // printf("nan nodal vf detected : %f %f %f %f\n",(float)vecP.norm(),(float)volf.norm(),(float)P.norm(),(float)FAct.norm()); + // } + gh_buffer.tuple(dim_c<12>,"grad",ei + offset) = gh_buffer.pack(dim_c<12>,"grad",ei + offset) + vf/* - rdamping*/; // gh_buffer.tuple(dim_c<12>,"grad",ei + offset) = gh_buffer.pack(dim_c<12>,"grad",ei + offset) - rdamping; // H += kd_beta*H/dt; @@ -813,6 +831,10 @@ struct FleshDynamicStepping : INode { // T lambda = model.lam; // T mu = model.mu; + + // auto gradn_after_elastic = TILEVEC_OPS::dot<12>(cudaPol,gh_buffer,"grad","grad"); + // std::cout << "gradn_after_elastic : " << gradn_after_elastic << std::endl; + auto nmEmbedVerts = b_verts.size(); cudaPol(zs::range(nmEmbedVerts), [ @@ -882,6 +904,8 @@ struct FleshDynamicStepping : INode { }); + // auto gradn_after_driver = TILEVEC_OPS::dot<12>(cudaPol,gh_buffer,"grad","grad"); + // std::cout << "gradn_after_driver : " << gradn_after_driver << std::endl; } @@ -1997,6 +2021,17 @@ struct FleshDynamicStepping : INode { },[](...) { throw std::runtime_error("unsupported anisotropic elasticity model"); })(models.getElasticModel(),models.getAnisoElasticModel()); + + // { + // auto gradn = TILEVEC_OPS::dot<12>(cudaPol,gh_buffer,"grad","grad"); + // std::cout << "gradn after elastic and inertia : " << gradn << std::endl; + // if(std::isnan(gradn)) { + // printf("nan gradn = %f detected after compute computeGradientAndHessian\n",gradn); + // // printf("Hn = ") + // throw std::runtime_error("nan gradn detected after compute computeGradientAndHessian"); + // } + // } + // std::cout << "computePositionConstraintGradientAndHessian : " << kverts.size() << std::endl; // the binder constraint gradient and hessian if(use_binder_constraint) { @@ -2270,7 +2305,7 @@ struct FleshDynamicStepping : INode { timer.tick(); spmat._vals.reset(0); - std::cout << "update gh_buffer spmat" << std::endl; + // std::cout << "update gh_buffer spmat" << std::endl; cudaPol(zs::range(eles.size()), [gh_buffer = proxy({},gh_buffer), @@ -2285,7 +2320,7 @@ struct FleshDynamicStepping : INode { update_hessian(spmat,inds,H,true); }); - std::cout << "update sttemp spmat" << std::endl; + // std::cout << "update sttemp spmat" << std::endl; cudaPol(zs::range(sttemp.size()), [sttemp = proxy({},sttemp),vsize = verts.size(),spmat = proxy(spmat)] ZS_LAMBDA(int vi) mutable { @@ -2297,7 +2332,7 @@ struct FleshDynamicStepping : INode { update_hessian(spmat,inds,H,true); }); - std::cout << "update vtemp spmat" << std::endl; + // std::cout << "update vtemp spmat" << std::endl; cudaPol(zs::range(vtemp.size()), [vtemp = proxy({},vtemp),vsize = verts.size(),spmat = proxy(spmat)] ZS_LAMBDA(int vi) mutable { @@ -2308,7 +2343,7 @@ struct FleshDynamicStepping : INode { update_hessian(spmat,inds,H,true); }); - std::cout << "update kinematics spmat" << std::endl; + // std::cout << "update kinematics spmat" << std::endl; if(use_kinematics_collision && kinematics.size() > 0) cudaPol(zs::range(ktris_vert_collision_buffer.size()),[ @@ -2319,7 +2354,7 @@ struct FleshDynamicStepping : INode { update_hessian(spmat,inds,H,true); }); - std::cout << "finish upate hessian" << std::endl; + // std::cout << "finish upate hessian" << std::endl; timer.tock("spmat evaluation"); #endif @@ -2341,6 +2376,13 @@ struct FleshDynamicStepping : INode { // std::cout << "Hn : " << Hn << std::endl; int nm_CG_iters = 0; #ifdef USE_SPARSE_MATRIX + // auto gradn = TILEVEC_OPS::dot<3>(cudaPol,vtemp,"grad","grad"); + // if(std::isnan(gradn)) { + // printf("nan gradn = %f detected\n",gradn); + // // printf("Hn = ") + // throw std::runtime_error("nan gradn detected"); + // } + if(turn_on_self_collision) nm_CG_iters = PCG::pcg_with_fixed_sol_solve<3>(cudaPol,vtemp,spmat,self_collision_fp_buffer,"dir","bou_tag","grad","P","inds","H",(T)cg_res,max_cg_iters,100); else diff --git a/projects/CuLagrange/fem/collision_energy/collision_utils.hpp b/projects/CuLagrange/fem/collision_energy/collision_utils.hpp index df631817d7..17561c59e6 100644 --- a/projects/CuLagrange/fem/collision_energy/collision_utils.hpp +++ b/projects/CuLagrange/fem/collision_energy/collision_utils.hpp @@ -21,6 +21,8 @@ namespace COLLISION_UTILS { using MATRIX3x12 = typename zs::vec; using MATRIX12 = typename zs::vec; + + /////////////////////////////////////////////////////////////////////// // should we reverse the direction of the force? /////////////////////////////////////////////////////////////////////// @@ -981,5 +983,137 @@ namespace COLLISION_UTILS { normal[0], normal[1], normal[2], intersect); } +// ps = [p_ea_0,p_ea_1,p_eb_0,p_eb_1] + constexpr bool compute_imminent_EE_collision_impulse(const VECTOR3 ps[4], + const VECTOR3 vs[4], + const REAL& scale, + const REAL& imminent_thickness, + const REAL minv[4], + VECTOR3 imps[4]) { + constexpr auto eps = 1e-7; + + VECTOR3 int_a{},int_b{}; + COLLISION_UTILS::IntersectLineSegments(ps[0],ps[1],ps[2],ps[3],int_a,int_b); + auto ra = (ps[0] - int_a).norm() / (ps[0] - ps[1]).norm(); + auto rb = (ps[2] - int_b).norm() / (ps[2] - ps[3]).norm(); + + VECTOR4 bary{}; + bary[0] = ra - 1; + bary[1] = -ra; + bary[2] = 1 - rb; + bary[3] = rb; + + auto cm = (REAL).0; + for(int i = 0;i != 4;++i) + cm += bary[i] * bary[i] * minv[i]; + if(cm < eps){ + // for(int i = 0;i != 4;++i) + // imps[i] = VECTOR3::zeros(); + return false;; + } + + auto pr = VECTOR3::zeros(); + auto vr = VECTOR3::zeros(); + for(int i = 0;i != 4;++i) { + pr += bary[i] * ps[i]; + vr += bary[i] * vs[i]; + } + + if(pr.norm() > imminent_thickness) { + return false; + } + + VECTOR3 collision_nrm{}; + if(pr.norm() < 100 * eps) + collision_nrm = (ps[0] - ps[1]).cross(ps[2] - ps[3]).normalized(); + else + collision_nrm = pr.normalized(); + + if(collision_nrm.dot(vr) > 0) + collision_nrm = (REAL)-1 * collision_nrm; + + auto vr_nrm = collision_nrm.dot(vr); + auto impulse = -collision_nrm * vr_nrm * scale; + + for(int i = 0;i != 4;++i) + imps[i] = bary[i] * (minv[i] / cm) * impulse; + + return true; + } + +// ps = [p_ea_0,p_ea_1,p_eb_0,p_eb_1] + constexpr bool compute_continous_EE_collision_impulse( + const VECTOR3 ps[4], + const VECTOR3 vs[4], + const REAL minv[4], + VECTOR3 imps[4]) { + constexpr auto eps = 1e-7; + + auto alpha = (REAL)1.0; + + auto has_dynamic_points = false; + for(int i = 0;i != 4;++i) + if(minv[i] > eps) + has_dynamic_points = true; + + + if(!has_dynamic_points || !ee_accd(ps[0],ps[1],ps[2],ps[3],vs[0],vs[1],vs[2],vs[3],(REAL)0.2,(REAL)0.0,alpha)) { + for(int i = 0;i != 4;++i) + imps[i] = VECTOR3::zeros(); + return false; + } + + VECTOR3 nps[4] = {}; + for(int i = 0;i != 4;++i) + nps[i] = ps[i] + alpha * vs[i]; + +// there will surely be an imminent collision + return compute_imminent_EE_collision_impulse(nps,vs,(REAL)1 - alpha,std::numeric_limits::max(),minv,imps); + } + +// ps = [t0,t1,t2,p] + constexpr bool compute_imminent_PT_collision_impulse(const VECTOR3 ps[4], + const VECTOR3 vs[4], + const REAL& scale, + const REAL& imminent_thickness, + const REAL minv[4], + VECTOR3 imps[4]) { + constexpr auto eps = 1e-7; + auto tnrm = LSL_GEO::facet_normal(ps[0],ps[1],ps[2]); + + auto seg = ps[3] - ps[0]; + auto project_dist = zs::abs(seg.dot(tnrm)); + if(project_dist > imminent_thickness) { + return false; + } + + VECTOR3 bary_centric{}; + LSL_GEO::pointBaryCentric(ps[0],ps[1],ps[2],ps[3],bary_centric); + + // if(distance > imminent_thickness) + // return false; + + auto bary_sum = zs::abs(bary_centric[0]) + zs::abs(bary_centric[1]) + zs::abs(bary_centric[2]); + if(bary_sum > (REAL)(1.0 + eps * 1000)) { + return false; + } + + VECTOR4 bary{-bary_centric[0],-bary_centric[1],-bary_centric[2],1}; + + auto pr = VECTOR3::zeros(); + auto vr = VECTOR3::zeros(); + for(int i = 0;i != 4;++i) { + pr += bary[i] * ps[i]; + vr += bary[i] * vs[i]; + } + + auto collision_nrm = LSL_GEO::facet_normal(ps[0],ps[1],ps[2]); + auto align = collision_nrm.dot(pr); + if(align < 0) + collision_nrm *= -1; + + auto relative_normal_velocity = vr.dot(collision_nrm); + } + }; }; \ No newline at end of file diff --git a/projects/CuLagrange/fem/collision_energy/evaluate_collision.hpp b/projects/CuLagrange/fem/collision_energy/evaluate_collision.hpp index 858923649d..2c2edab20d 100644 --- a/projects/CuLagrange/fem/collision_energy/evaluate_collision.hpp +++ b/projects/CuLagrange/fem/collision_energy/evaluate_collision.hpp @@ -801,6 +801,823 @@ inline int do_tetrahedra_surface_mesh_and_kinematic_boundary_collision_detection return csPT.size(); } + + +// template +// void calc_imminent_self_PT_collision_impulse(Pol& pol, +// const PosTileVec& verts,const zs::SmallString& xtag,const zs::SmallString& vtag, +// const TriTileVec& tris, +// const HalfEdgeTileVec& halfedges, +// const REAL& thickness, +// ImpulseBuffer& impulse_buffer, +// ImpulseCount& impulse_count) { +// using namespace zs; +// constexpr auto space = RM_CVREF_T(pol)::exec_tag::value; +// constexpr auto exec_tag = wrapv{}; +// using vec3 = zs::vec; +// using vec4 = zs::vec; +// using vec4i = zs::vec; +// constexpr auto eps = (T)1e-6; + +// auto triBvh = bvh_t{}; +// auto triBvs = retrieve_bounding_volumes(pol,verts,tris,wrapv<3>{},0,xtag); +// triBvh.build(pol,triBvs); + +// pol(zs::range(verts.size()),[ +// xtag = xtag, +// verts = proxy({},verts), +// tris = proxy({},tris), +// thickness = thickness, +// eps = eps, +// halfedges = proxy({},halfedges), +// triBvh = proxy(triBvh), +// impulse_buffer = proxy(impulse_buffer), +// impulse_count = proxy(impulse_count)] ZS_LAMBDA(int vi) mutable { +// vec3 ps[4] = {}; +// ps[3] = verts.pack(dim_c<3>,xtag,vi); +// vec3 vs[4] = {}; +// vs[3] = verts.pack(dim_c<3>,vtag,vi); +// vec4i inds{}; +// inds[3] = vi; + +// auto bv = bv_t{get_bounding_box(ps[3] - thickness,ps[3] + thickness)}; +// auto calc_impulse_for_close_proximity = [&](int ti) { +// auto tri = tris.pack(dim_c<3>,"inds",ti,int_c); +// for(int i = 0;i != 3;++i) +// if(tri[i] == vi) +// return; + +// bool has_dynamic_points = false; +// if(verts("minv",vi) > eps) +// has_dynamic_points = true; +// for(int i = 0;i != 3;++i) +// if(verts("minv",tri[i]) > eps) +// has_dynamic_points = true; +// if(!has_dynamic_points) +// return; + +// for(int i = 0;i != 3;++i) { +// ps[i] = verts.pack(dim_c<3>,xtag,tri[i]); +// vs[i] = verts.pack(dim_c<3>,vtag,tri[i]); +// inds[i] = tri[i]; +// } + +// auto tnrm = LSL_GEO::facet_normal(ps[0],ps[1],ps[2]); +// auto seg = ps[3] - ps[0]; +// auto project_dist = zs::abs(seg.dot(tnrm)); +// if(project_dist > thickness) +// return; + +// // auto barySum = (T)1.0; +// vec3 bary_centric{}; +// auto distance = LSL_GEO::pointTriangleDistance(ps[0],ps[1],ps[2],ps[3],bary_centric); + +// if(distance > thickness) +// return; + +// auto bary_sum = zs::abs(bary_centric[0]) + zs::abs(bary_centric[1]) + zs::abs(bary_centric[2]); +// if(bary_sum > (T)(1.0 + eps * 10)) { +// vec3 bnrms[3] = {}; +// auto hi = zs::reinterpret_bits(tris("he_inds",ti)); +// for(int i = 0;i != 3;++i){ +// auto edge_normal = tnrm; +// auto opposite_hi = zs::reinterpret_bits(halfedges("opposite_he",hi)); +// if(opposite_hi >= 0){ +// auto nti = zs::reinterpret_bits(halfedges("to_face",opposite_hi)); +// auto ntri = tris.pack(dim_c<3>,"inds",nti,int_c); +// auto ntnrm = LSL_GEO::facet_normal( +// verts.pack(dim_c<3>,xtag,ntri[0]), +// verts.pack(dim_c<3>,xtag,ntri[1]), +// verts.pack(dim_c<3>,xtag,ntri[2])); +// edge_normal = tnrm + ntnrm; +// edge_normal = edge_normal/(edge_normal.norm() + eps); +// } +// auto e01 = ts[(i + 1) % 3] - ts[(i + 0) % 3]; +// bnrms[i] = edge_normal.cross(e01).normalized(); +// hi = zs::reinterpret_bits(halfedges("next_he",hi)); +// } +// for(int i = 0;i != 3;++i){ +// seg = p - ts[i]; +// if(bnrms[i].dot(seg) < 0) +// return; +// } +// } + +// vec4 bary{-bary_centric[0],-bary_centric[1],-bary_centric[2],1}; +// auto pr = vec3::zeros(); +// auto vr = vec3::zeros(); +// for(int i = 0;i != 4;++i) { +// pr += bary[i] * ps[i]; +// vr += bary[i] * vs[i]; +// } + +// auto collision_nrm = pr.normalized(); +// auto relative_normal_velocity = vr.dot(collision_nrm); + +// auto I = relative_normal_velocity < 0 ? relative_normal_velocity : (T)0; +// impulse = -collision_nrm * I; + +// auto beta = (T)0; +// for(int i = 0;i != 4;++i) +// beta += bary[i] * bary[i] * verts("minv",inds[i]); +// impulse /= beta; + +// for(int i = 0;i != 4;++i) { +// atomic_add(exec_tag,&impulse_count[inds[i]],1); +// for(int d = 0;d != 3;++d) +// atomic_add(exec_tag,&impulse_buffer[inds[i]][d],impulse[d] * bary[i]); +// } +// }; +// triBvh.iter_neighbors(bv,calc_impulse_for_close_proximity); +// }); +// } + + +template +void calc_imminent_self_PT_collision_impulse(Pol& pol, + const PosTileVec& verts,const zs::SmallString& xtag,const zs::SmallString& vtag, + const TriTileVec& tris, + const HalfEdgeTileVec& halfedges, + const REAL& thickness, + size_t buffer_offset, + CollisionBuffer& imminent_collision_buffer) { + using namespace zs; + constexpr auto space = RM_CVREF_T(pol)::exec_tag::value; + // constexpr auto exec_tag = wrapv{}; + using vec3 = zs::vec; + using vec4 = zs::vec; + using vec4i = zs::vec; + constexpr auto eps = (T)1e-6; + constexpr auto MAX_PT_COLLISION_PAIRS = 1000000; + + zs::bht csPT{verts.get_allocator(),MAX_PT_COLLISION_PAIRS}; + csPT.reset(pol,true); + + auto triBvh = bvh_t{}; + auto triBvs = retrieve_bounding_volumes(pol,verts,tris,wrapv<3>{},thickness / (REAL)2,xtag); + triBvh.build(pol,triBvs); + + pol(zs::range(verts.size()),[ + xtag = xtag, + verts = proxy({},verts), + tris = proxy({},tris), + thickness = thickness, + eps = eps, + halfedges = proxy({},halfedges), + triBvh = proxy(triBvh), + // imminent_collision_buffer = proxy({},imminent_collision_buffer), + csPT = proxy(csPT)] ZS_LAMBDA(int vi) mutable { + auto p = verts.pack(dim_c<3>,xtag,vi); + auto bv = bv_t{get_bounding_box(p - thickness/(REAL)2,p + thickness/(REAL)2)}; + auto do_close_proximity_detection = [&](int ti) { + auto tri = tris.pack(dim_c<3>,"inds",ti,int_c); + for(int i = 0;i != 3;++i) + if(tri[i] == vi) + return; + + bool has_dynamic_points = false; + if(verts("minv",vi) > eps) + has_dynamic_points = true; + for(int i = 0;i != 3;++i) + if(verts("minv",tri[i]) > eps) + has_dynamic_points = true; + if(!has_dynamic_points) + return; + + vec3 ts[3] = {}; + for(int i = 0;i != 3;++i) + ts[i] = verts.pack(dim_c<3>,xtag,tri[i]); + + auto tnrm = LSL_GEO::facet_normal(ts[0],ts[1],ts[2]); + auto seg = p - ts[0]; + auto project_dist = zs::abs(seg.dot(tnrm)); + if(project_dist > thickness) + return; + + // auto barySum = (T)1.0; + vec3 bary_centric{}; + auto distance = LSL_GEO::pointTriangleDistance(ts[0],ts[1],ts[2],p,bary_centric); + + if(distance > thickness) + return; + + auto bary_sum = zs::abs(bary_centric[0]) + zs::abs(bary_centric[1]) + zs::abs(bary_centric[2]); + if(bary_sum > (T)(1.0 + eps * 100)) { + return; + vec3 bnrms[3] = {}; + auto hi = zs::reinterpret_bits(tris("he_inds",ti)); + for(int i = 0;i != 3;++i){ + auto edge_normal = tnrm; + auto opposite_hi = zs::reinterpret_bits(halfedges("opposite_he",hi)); + if(opposite_hi >= 0){ + auto nti = zs::reinterpret_bits(halfedges("to_face",opposite_hi)); + auto ntri = tris.pack(dim_c<3>,"inds",nti,int_c); + auto ntnrm = LSL_GEO::facet_normal( + verts.pack(dim_c<3>,xtag,ntri[0]), + verts.pack(dim_c<3>,xtag,ntri[1]), + verts.pack(dim_c<3>,xtag,ntri[2])); + edge_normal = tnrm + ntnrm; + edge_normal = edge_normal/(edge_normal.norm() + eps); + } + auto e01 = ts[(i + 1) % 3] - ts[(i + 0) % 3]; + bnrms[i] = edge_normal.cross(e01).normalized(); + hi = zs::reinterpret_bits(halfedges("next_he",hi)); + } + for(int i = 0;i != 3;++i){ + seg = p - ts[i]; + if(bnrms[i].dot(seg) < 0) + return; + } + } + csPT.insert(zs::vec{vi,ti}); + }; + + triBvh.iter_neighbors(bv,do_close_proximity_detection); + }); + + imminent_collision_buffer.resize(csPT.size() + buffer_offset); + pol(zip(zs::range(csPT.size()),csPT._activeKeys),[ + csPT = proxy(csPT), + imminent_collision_buffer = proxy({},imminent_collision_buffer), + xtag = xtag,vtag = vtag, + buffer_offset = buffer_offset, + verts = proxy({},verts), + tris = proxy({},tris)] ZS_LAMBDA(auto id,const auto& pair) mutable { + auto vi = pair[0]; + auto ti = pair[1]; + auto tri = tris.pack(dim_c<3>,"inds",ti,int_c); + + vec4i inds{tri[0],tri[1],tri[2],vi}; + vec3 ps[4] = {}; + for(int i = 0;i != 4;++i) + ps[i] = verts.pack(dim_c<3>,xtag,inds[i]); + vec3 vs[4] = {}; + for(int i = 0;i != 4;++i) + vs[i] = verts.pack(dim_c<3>,vtag,inds[i]); + + vec3 bary_centric{}; + LSL_GEO::pointBaryCentric(ps[0],ps[1],ps[2],ps[3],bary_centric); + + for(int i = 0;i != 3;++i) + bary_centric[i] = bary_centric[i] < 0 ? 0 : bary_centric[i]; + auto barySum = bary_centric[0] + bary_centric[1] + bary_centric[2]; + bary_centric = bary_centric / barySum; + + vec4 bary{-bary_centric[0],-bary_centric[1],-bary_centric[2],1}; + + auto pr = vec3::zeros(); + auto vr = vec3::zeros(); + for(int i = 0;i != 4;++i) { + pr += bary[i] * ps[i]; + vr += bary[i] * vs[i]; + } + + auto collision_nrm = LSL_GEO::facet_normal(ps[0],ps[1],ps[2]); + auto align = collision_nrm.dot(pr); + if(align < 0) + collision_nrm *= -1; + // LSL_GEO::facet_normal(ps[0],ps[1],ps[2]); + auto relative_normal_velocity = vr.dot(collision_nrm); + + imminent_collision_buffer.tuple(dim_c<4>,"bary",id + buffer_offset) = bary; + imminent_collision_buffer.tuple(dim_c<4>,"inds",id + buffer_offset) = inds.reinterpret_bits(float_c); + auto I = relative_normal_velocity < 0 ? relative_normal_velocity : (T)0; + imminent_collision_buffer.tuple(dim_c<3>,"impulse",id + buffer_offset) = -collision_nrm * I; + imminent_collision_buffer.tuple(dim_c<3>,"collision_normal",id + buffer_offset) = collision_nrm; + }); +} + + +template +void calc_imminent_self_EE_collision_impulse(Pol& pol, + const PosTileVec& verts,const zs::SmallString& xtag,const zs::SmallString& vtag, + const EdgeTileVec& edges, + const REAL& thickness, + size_t buffer_offset, + CollisionBuffer& imminent_collision_buffer) { + using namespace zs; + constexpr auto space = RM_CVREF_T(pol)::exec_tag::value; + // constexpr auto exec_tag = wrapv{}; + using vec2 = zs::vec; + using vec3 = zs::vec; + using vec4 = zs::vec; + using vec2i = zs::vec; + using vec4i = zs::vec; + constexpr auto eps = (T)1e-6; + constexpr auto MAX_PT_COLLISION_PAIRS = 1000000; + zs::bht csEE{verts.get_allocator(),MAX_PT_COLLISION_PAIRS}; + csEE.reset(pol,true); + + auto edgeBvh = bvh_t{}; + auto bvs = retrieve_bounding_volumes(pol,verts,edges,wrapv<2>{},thickness / (T)2,xtag); + edgeBvh.build(pol,bvs); + + pol(zs::range(edges.size()),[ + xtag = xtag, + verts = proxy({},verts), + edges = proxy({},edges), + thickness = thickness, + eps = eps, + edgeBvh = proxy(edgeBvh), + csEE = proxy(csEE)] ZS_LAMBDA(int ei) mutable { + auto ea = edges.pack(dim_c<2>,"inds",ei,int_c); + vec3 pas[2] = {}; + for(int i = 0;i != 2;++i) + pas[i] = verts.pack(dim_c<3>,xtag,ea[i]); + auto bv = bv_t{get_bounding_box(pas[0],pas[1])}; + bv._max += thickness/2; + bv._min -= thickness/2; + auto la = (pas[0] - pas[1]).norm(); + + auto do_close_proximity_detection = [&](int nei) mutable { + if(ei >= nei) + return; + auto eb = edges.pack(dim_c<2>,"inds",nei,int_c); + for(int i = 0;i != 2;++i){ + if(eb[i] == ea[0] || eb[i] == ea[1]) + return; + } + + bool has_dynamic_points = false; + for(int i = 0;i != 2;++i) { + if(verts("minv",ea[i]) > eps) + has_dynamic_points = true; + if(verts("minv",eb[i]) > eps) + has_dynamic_points = true; + } + if(!has_dynamic_points) + return; + + vec3 pbs[2] = {}; + for(int i = 0;i != 2;++i) + pbs[i] = verts.pack(dim_c<3>,xtag,eb[i]); + + auto cp = (pas[0] - pas[1]).cross(pbs[0] - pbs[1]).norm(); + // if(cp < eps * 100) { + // auto ac = (pas[0] + pas[1]) / (T)2.0; + // auto bc = (pbs[0] + pbs[1]) / (T)2.0; + // if((ac - bc).norm() < thickness) + // csEE.insert(vec2i{ei,nei}); + + // return; + // } + + vec3 int_a{},int_b{}; + COLLISION_UTILS::IntersectLineSegments(pas[0],pas[1],pbs[0],pbs[1],int_a,int_b); + auto dist = (int_a - int_b).norm(); + if(dist > thickness) + return; + + auto lb = (pbs[0] - pbs[1]).norm(); + + auto ra = (pas[0] - int_a).norm() / la; + auto rb = (pbs[0] - int_b).norm() / lb; + + if(ra < 100 * eps || ra > 1 - 100 * eps) + return; + if(rb < 100 * eps || rb > 1 - 100 * eps) + return; + + csEE.insert(vec2i{ei,nei}); + }; + edgeBvh.iter_neighbors(bv,do_close_proximity_detection); + }); + + // printf("nm_EE_collision_pairs : %d %d\n",(int)csEE.size(),(int)edges.size()); + + imminent_collision_buffer.resize(csEE.size() + buffer_offset); + pol(zip(zs::range(csEE.size()),csEE._activeKeys),[ + verts = proxy({},verts), + edges = proxy({},edges), + buffer_offset = buffer_offset, + xtag = xtag, + vtag = vtag, + eps = eps, + imminent_collision_buffer = proxy({},imminent_collision_buffer)] ZS_LAMBDA(auto ci,const auto& pair) mutable { + auto ei = pair[0]; + auto nei = pair[1]; + + auto ea = edges.pack(dim_c<2>,"inds",ei,int_c); + auto eb = edges.pack(dim_c<2>,"inds",nei,int_c); + vec4i inds{ea[0],ea[1],eb[0],eb[1]}; + + vec3 ps[4] = {}; + vec3 vs[4] = {}; + for(int i = 0;i != 4;++i) { + ps[i] = verts.pack(dim_c<3>,xtag,inds[i]); + vs[i] = verts.pack(dim_c<3>,vtag,inds[i]); + } + + vec3 int_a{},int_b{}; + COLLISION_UTILS::IntersectLineSegments(ps[0],ps[1],ps[2],ps[3],int_a,int_b); + + auto la = (ps[0] - ps[1]).norm(); + auto lb = (ps[2] - ps[3]).norm(); + + auto ra = (ps[0] - int_a).norm() / la; + auto rb = (ps[2] - int_b).norm() / lb; + + vec4 bary{ra - 1,-ra,1 - rb,rb}; + + auto pr = vec3::zeros(); + auto vr = vec3::zeros(); + for(int i = 0;i != 4;++i) { + pr += bary[i] * ps[i]; + vr += bary[i] * vs[i]; + } + + auto collision_nrm = (ps[0] - ps[1]).cross(ps[2] - ps[3]).normalized(); + // if(collision_nrm.norm() < eps * 100) { + + // } + auto align = collision_nrm.dot(pr); + if(align < 0) + collision_nrm *= -1; + auto relative_normal_velocity = vr.dot(collision_nrm); + + imminent_collision_buffer.tuple(dim_c<4>,"bary",ci + buffer_offset) = bary; + imminent_collision_buffer.tuple(dim_c<4>,"inds",ci + buffer_offset) = inds.reinterpret_bits(float_c); + auto I = relative_normal_velocity < 0 ? relative_normal_velocity : (T)0; + imminent_collision_buffer.tuple(dim_c<3>,"impulse",ci + buffer_offset) = -collision_nrm * I; + imminent_collision_buffer.tuple(dim_c<3>,"collision_normal",ci + buffer_offset) = collision_nrm; + }); + + // printf("Eval EE collision impulse\n"); +} + + + +template +void calc_continous_self_PT_collision_impulse(Pol& pol, + const InverseMassTileVec& invMass, + const PosTileVec& verts,const zs::SmallString& xtag,const zs::SmallString& vtag, + const TrisTileVec& tris, + // const THICKNESS_REAL& thickness, + TriBvh& triCCDBvh, + bool refit_bvh, + ImpulseBuffer& impulse_buffer, + ImpulseCount& impulse_count) { + using namespace zs; + constexpr auto space = RM_CVREF_T(pol)::exec_tag::value; + // constexpr auto exec_tag = wrapv{}; + + using vec2 = zs::vec; + using vec3 = zs::vec; + using vec4 = zs::vec; + using vec2i = zs::vec; + using vec4i = zs::vec; + constexpr auto eps = (T)1e-6; + + auto bvs = retrieve_bounding_volumes(pol,verts,tris,verts,wrapv<3>{},(T)1.0,(T)0,xtag,vtag); + if(refit_bvh) + triCCDBvh.refit(pol,bvs); + else + triCCDBvh.build(pol,bvs); + + pol(zs::range(verts.size()),[ + invMass = proxy({},invMass), + xtag = xtag, + vtag = vtag, + verts = proxy({},verts), + tris = proxy({},tris), + // csPT = proxy(csPT), + // thickness = thickness, + impulse_buffer = proxy(impulse_buffer), + impulse_count = proxy(impulse_count), + eps = eps, + exec_tag = wrapv{}, + bvh = proxy(triCCDBvh)] ZS_LAMBDA(int vi) mutable { + auto p = verts.pack(dim_c<3>,xtag,vi); + auto v = verts.pack(dim_c<3>,vtag,vi); + + bv_t bv{p, p + v}; + // bv._min -= thickness * (T).5; + // bv._max += thickness * (T).5; + + vec3 ps[4] = {}; + ps[3] = p; + vec3 vs[4] = {}; + vs[3] = v; + vec4 bary{0,0,0,1}; + vec4i inds{-1,-1,-1,vi}; + + auto do_close_proximity_detection = [&](int ti) mutable { + auto tri = tris.pack(dim_c<3>,"inds",ti,int_c); + for(int i = 0;i != 3;++i) + if(tri[i] == vi) + return; + + bool has_dynamic_points = verts("minv",vi) > eps; + for(int i = 0;i != 3;++i) { + if(invMass("minv",tri[i]) > eps) + has_dynamic_points = true; + } + if(!has_dynamic_points) + return; + + for(int i = 0;i != 3;++i) { + ps[i] = verts.pack(dim_c<3>,xtag,tri[i]); + vs[i] = verts.pack(dim_c<3>,vtag,tri[i]); + inds[i] = tri[i]; + } + + auto alpha = (T)1.0; + if(!pt_accd(ps[3],ps[0],ps[1],ps[2],vs[3],vs[0],vs[1],vs[2],(T)0.2,(T)0,alpha)) + return; + + vec3 nps[4] = {}; + for(int i = 0;i != 4;++i) + nps[i] = ps[i] + vs[i] * alpha; + + vec3 bary_centric{}; + LSL_GEO::pointBaryCentric(nps[0],nps[1],nps[2],nps[3],bary_centric); + auto ori_bary = bary_centric; + for(int i = 0;i != 3;++i) + bary_centric[i] = bary_centric[i] < 0 ? 0 : bary_centric[i]; + auto barySum = bary_centric[0] + bary_centric[1] + bary_centric[2]; + bary_centric = bary_centric / barySum; + + for(int i = 0;i != 3;++i) + bary[i] = -bary_centric[i]; + + auto rv = vec3::zeros(); + for(int i = 0;i != 4;++i) { + rv += vs[i] * bary[i]; + } + + auto collision_nrm = LSL_GEO::facet_normal(nps[0],nps[1],nps[2]); + if(collision_nrm.dot(rv) > 0) + collision_nrm *= -1; + auto rv_nrm = collision_nrm.dot(rv); + + auto cm = (T).0; + for(int i = 0;i != 4;++i) + cm += bary[i] * bary[i] * invMass("minv",inds[i]); + if(cm < eps) + return; + + auto impulse = -collision_nrm * rv_nrm * ((T)1 - alpha); + // printf("find collision pairs[%d %d] with ccd : %f impulse : \n%f %f %f\n%f %fbary : %f %f %f %f\nminv : %f %f %f %f\n",ti,vi,(float)alpha, + // (float)impulse[0],(float)impulse[1],(float)impulse[2], + // (float)rv_nrm,(float)cm, + // (float)bary[0],(float)bary[1],(float)bary[2],(float)bary[3], + // (float)invMass("minv",inds[0]), + // (float)invMass("minv",inds[1]), + // (float)invMass("minv",inds[2]), + // (float)invMass("minv",inds[3])); + + for(int i = 0;i != 4;++i) { + auto beta = (bary[i] * invMass("minv",inds[i])) / cm; + atomic_add(exec_tag,&impulse_count[inds[i]],1); + for(int d = 0;d != 3;++d) + atomic_add(exec_tag,&impulse_buffer[inds[i]][d],impulse[d] * beta); + } + }; + bvh.iter_neighbors(bv,do_close_proximity_detection); + }); +} + +template +void calc_continous_self_EE_collision_impulse(Pol& pol, + const InverseMassTileVec& invMass, + const PosTileVec& verts,const zs::SmallString& xtag,const zs::SmallString& vtag, + const EdgeTileVec& edges, + EdgeBvh& edgeCCDBvh, + bool refit_bvh, + ImpulseBuffer& impulse_buffer, + ImpulseCountBuffer& impulse_count) { + using namespace zs; + constexpr auto space = RM_CVREF_T(pol)::exec_tag::value; + // constexpr auto exec_tag = wrapv{}; + + using vec2 = zs::vec; + using vec3 = zs::vec; + using vec4 = zs::vec; + using vec2i = zs::vec; + using vec4i = zs::vec; + constexpr auto eps = (T)1e-6; + + // auto edgeCCDBvh = bvh_t{}; + auto edgeBvs = retrieve_bounding_volumes(pol,verts,edges,verts,wrapv<2>{},(T)1.0,(T)0,xtag,vtag); + if(refit_bvh) + edgeCCDBvh.refit(pol,edgeBvs); + else + edgeCCDBvh.build(pol,edgeBvs); + + pol(zs::range(edges.size()),[ + xtag = xtag, + vtag = vtag, + verts = proxy({},verts), + edges = proxy({},edges), + invMass = proxy({},invMass), + impulse_buffer = proxy(impulse_buffer), + impulse_count = proxy(impulse_count), + // thickness = thickness, + eps = eps, + exec_tag = wrapv{}, + edgeBvs = proxy(edgeBvs), + bvh = proxy(edgeCCDBvh)] ZS_LAMBDA(int ei) mutable { + auto ea = edges.pack(dim_c<2>,"inds",ei,int_c); + vec3 ps[4] = {}; + ps[0] = verts.pack(dim_c<3>,xtag,ea[0]); + ps[1] = verts.pack(dim_c<3>,xtag,ea[1]); + vec3 vs[4] = {}; + vs[0] = verts.pack(dim_c<3>,vtag,ea[0]); + vs[1] = verts.pack(dim_c<3>,vtag,ea[1]); + + vec4i inds{ea[0],ea[1],-1,-1}; + + T minvs[4] = {}; + minvs[0] = verts("minv",ea[0]); + minvs[1] = verts("minv",ea[1]); + + vec3 imps[4] = {}; + + auto bv = edgeBvs[ei]; + + auto do_close_proximity_detection = [&](int nei) mutable { + if(ei >= nei) + return; + auto eb = edges.pack(dim_c<2>,"inds",nei,int_c); + for(int i = 0;i != 2;++i){ + if(eb[i] == ea[0] || eb[i] == ea[1]) + return; + } + + for(int i = 0;i != 2;++i) { + ps[i + 2] = verts.pack(dim_c<3>,xtag,eb[i]); + vs[i + 2] = verts.pack(dim_c<3>,vtag,eb[i]); + inds[i + 2] = eb[i]; + minvs[i + 2] = verts("minv",eb[i]); + } +// The orginal reference code +#if 0 + auto has_dynamic_points = false; + for(int i = 0;i != 4;++i) + if(minvs[i] > eps) + has_dynamic_points = true; + if(!has_dynamic_points) + return; + + auto alpha = (T)1.0; + if(!ee_accd(ps[0],ps[1],ps[2],ps[3],vs[0],vs[1],vs[2],vs[3],(T)0.2,(T)0.0,alpha)) + return; + + vec3 nps[4] = {}; + for(int i = 0;i != 4;++i) + nps[i] = ps[i] + alpha * vs[i]; + + + vec3 int_a{},int_b{}; + COLLISION_UTILS::IntersectLineSegments(nps[0],nps[1],nps[2],nps[3],int_a,int_b); + + auto ra = (nps[0] - int_a).norm() / (nps[0] - nps[1]).norm(); + auto rb = (nps[2] - int_b).norm() / (nps[2] - nps[3]).norm(); + + vec4 bary{ra - 1,-ra,1 - rb,rb}; + auto pr = vec3::zeros(); + auto vr = vec3::zeros(); + for(int i = 0;i != 4;++i) { + pr += bary[i] * nps[i]; + vr += bary[i] * vs[i]; + } + + vec3 collision_nrm = {}; + if(pr.norm() < 100 * eps) + collision_nrm = (nps[0] - nps[1]).cross(nps[2] - nps[3]).normalized(); + else + collision_nrm = pr.normalized(); + if(collision_nrm.dot(vr) > 0) + collision_nrm = (T)-1 * collision_nrm; + + auto vr_nrm = collision_nrm.dot(vr); + + auto cm = (T).0; + for(int i = 0;i != 4;++i) + cm += bary[i] * bary[i] * invMass("minv",inds[i]); + if(cm < eps) + return; + + auto impulse = -collision_nrm * vr_nrm * ((T)1 - alpha); + + for(int i = 0;i != 4;++i) { + auto beta = (bary[i] * invMass("minv",inds[i])) / cm; + atomic_add(exec_tag,&impulse_count[inds[i]],1); + for(int d = 0;d != 3;++d) + atomic_add(exec_tag,&impulse_buffer[inds[i]][d],impulse[d] * beta); + } +#else + if(!compute_continous_EE_collision_impulse(ps,vs,minvs,imps)) + return; + for(int i = 0;i != 4;++i) { + atomic_add(exec_tag,&impulse_count[inds[i]],1); + for(int d = 0;d != 3;++d) + atomic_add(exec_tag,&impulse_buffer[inds[i]][d],imps[i][d]); + } +#endif + }; + bvh.iter_neighbors(bv,do_close_proximity_detection); + }); +} + + +template +void apply_impulse(Pol& pol, + PosTileVec& verts,const zs::SmallString& vtag, + const T& imminent_restitution_rate, + const T& imminent_relaxation_rate, + CollisionBuffer& imminent_collision_buffer) { + using namespace zs; + constexpr auto space = RM_CVREF_T(pol)::exec_tag::value; + // constexpr auto exec_tag = wrapv{}; + using vec3 = zs::vec; + constexpr auto eps = (T)1e-6; + + zs::Vector impulse_buffer{verts.get_allocator(),verts.size()}; + pol(zs::range(impulse_buffer),[] ZS_LAMBDA(auto& imp) mutable {imp = vec3::zeros();}); + zs::Vector impulse_count{verts.get_allocator(),verts.size()}; + pol(zs::range(impulse_count),[] ZS_LAMBDA(auto& c) mutable {c = 0;}); + + pol(zs::range(imminent_collision_buffer.size()),[ + verts = proxy({},verts), + vtag = zs::SmallString(vtag), + imminent_collision_buffer = proxy({},imminent_collision_buffer), + exec_tag = wrapv{}, + eps = eps, + restitution_rate = imminent_restitution_rate, + impulse_count = proxy(impulse_count), + impulse_buffer = proxy(impulse_buffer)] ZS_LAMBDA(auto ci) mutable { + auto inds = imminent_collision_buffer.pack(dim_c<4>,"inds",ci,int_c); + auto bary = imminent_collision_buffer.pack(dim_c<4>,"bary",ci); + auto impulse = imminent_collision_buffer.pack(dim_c<3>,"impulse",ci); + if(impulse.norm() < eps) + return; + + T cminv = 0; + for(int i = 0;i != 4;++i) + cminv += bary[i] * bary[i] * verts("minv",inds[i]); + // impulse /= beta; + + for(int i = 0;i != 4;++i) { + auto beta = verts("minv",inds[i]) * bary[i] / cminv; + atomic_add(exec_tag,&impulse_count[inds[i]],1); + for(int d = 0;d != 3;++d) + atomic_add(exec_tag,&impulse_buffer[inds[i]][d],impulse[d] * beta); + } + + }); + pol(zs::range(verts.size()),[ + verts = proxy({},verts), + vtag = zs::SmallString(vtag), + impulse_buffer = proxy(impulse_buffer), + impulse_count = proxy(impulse_count), + relaxation_rate = imminent_relaxation_rate, + eps = eps, + exec_tag = wrapv{}] ZS_LAMBDA(int vi) mutable { + if(impulse_buffer[vi].norm() < eps || impulse_count[vi] == 0) + return; + auto impulse = relaxation_rate * impulse_buffer[vi] / (T)impulse_count[vi]; + // auto dp = impulse * verts("minv",vi); + + for(int i = 0;i != 3;++i) + atomic_add(exec_tag,&verts(vtag,i,vi),impulse[i]); + }); +} + template nmIncidentTris{verts.get_allocator(),verts.size()}; - cudaPol(zs::range(nmIncidentTris),[] ZS_LAMBDA(int& count) mutable {count = 0;}); + // zs::Vector nmIncidentTris{verts.get_allocator(),verts.size()}; + zs::Vector nodal_area{verts.get_allocator(),verts.size()}; + + // cudaPol(zs::range(nmIncidentTris),[] ZS_LAMBDA(auto& count) mutable {count = 0;}); + cudaPol(zs::range(nodal_area),[] ZS_LAMBDA(auto& A) mutable {A = 0;}); cudaPol(zs::range(tris.size()),[ exec_tag, attrName = zs::SmallString(attrName), tris = proxy({},tris), - nmIncidentTris = proxy(nmIncidentTris), + nodal_area = proxy(nodal_area), + // nmIncidentTris = proxy(nmIncidentTris), verts = proxy({},verts)] ZS_LAMBDA(int ti) mutable { auto tri = tris.pack(dim_c<3>,"inds",ti,int_c); zs::vec tV[3] = {}; @@ -57,17 +61,17 @@ struct ZSComputeSurfaceArea : zeno::INode { auto A = LSL_GEO::area(tV[0],tV[1],tV[2]); tris(attrName,ti) = A; for(int i = 0;i != 3;++i) { - atomic_add(exec_tag,&verts(attrName,tri[i]),A); - atomic_add(exec_tag,&nmIncidentTris[0],(int)1); + atomic_add(exec_tag,&nodal_area[tri[i]],A / (T)3.0); + // atomic_add(exec_tag,&nmIncidentTris[0],(int)1); } - }); + }); cudaPol(zs::range(verts.size()),[ verts = proxy({},verts), attrName = zs::SmallString(attrName), - nmIncidentTris = proxy(nmIncidentTris)] ZS_LAMBDA(int vi) mutable { - if(nmIncidentTris[vi] > 0) - verts(attrName,vi) = verts(attrName,vi) / (T)nmIncidentTris[vi]; + nodal_area = proxy(nodal_area)] ZS_LAMBDA(int vi) mutable { + // if(nmIncidentTris[vi] > 0) + verts(attrName,vi) = nodal_area[vi]; }); set_output("zsparticles",zsparticles); diff --git a/projects/CuLagrange/geometry/CollisionVis.cu b/projects/CuLagrange/geometry/CollisionVis.cu index beb0d4f859..d8b97c87f3 100644 --- a/projects/CuLagrange/geometry/CollisionVis.cu +++ b/projects/CuLagrange/geometry/CollisionVis.cu @@ -470,8 +470,8 @@ namespace zeno { },tri_buffer.size()}; auto& halfedges = (*zsparticles)[ZenoParticles::s_surfHalfEdgeTag]; - auto nm_insts = do_global_self_intersection_analysis_on_surface_mesh_info( - cudaPol,verts_buffer,"x",tri_buffer,halfedges,inst_buffer_info,gia_res,false); + // auto nm_insts = do_global_self_intersection_analysis_on_surface_mesh_info( + // cudaPol,verts_buffer,"x",tri_buffer,halfedges,inst_buffer_info,gia_res,false); // zs::bht conn_of_first_ring{halfedges.get_allocator(),halfedges.size()}; auto ring_mask_width = do_global_self_intersection_analysis(cudaPol, verts_buffer,"x",tri_buffer,halfedges,gia_res,tris_gia_res); diff --git a/projects/CuLagrange/geometry/Topology.cu b/projects/CuLagrange/geometry/Topology.cu index 9e0bbe274f..da09523af0 100644 --- a/projects/CuLagrange/geometry/Topology.cu +++ b/projects/CuLagrange/geometry/Topology.cu @@ -24,133 +24,168 @@ struct BuildSurfaceHalfEdgeStructure : zeno::INode { using namespace zs; using vec2i = zs::vec; using vec3i = zs::vec; + constexpr auto space = zs::execspace_e::cuda; auto zsparticles = get_input("zsparticles"); - if(!zsparticles->hasAuxData(ZenoParticles::s_surfTriTag) && zsparticles->category == ZenoParticles::category_e::tet) - throw std::runtime_error("the input tet zsparticles has no surface tris"); - // if(!zsparticles->hasAuxData(ZenoParticles::s_surfEdgeTag)) - // throw std::runtime_error("the input zsparticles has no surface lines"); - if(!zsparticles->hasAuxData(ZenoParticles::s_surfVertTag) && zsparticles->category == ZenoParticles::category_e::tet) - throw std::runtime_error("the input tet zsparticles has no surface points"); - - auto& tris = zsparticles->category == ZenoParticles::category_e::tet ? (*zsparticles)[ZenoParticles::s_surfTriTag] : zsparticles->getQuadraturePoints(); - // auto& lines = (*zsparticles)[ZenoParticles::s_surfEdgeTag]; - auto& points = zsparticles->category == ZenoParticles::category_e::tet ? (*zsparticles)[ZenoParticles::s_surfVertTag] : zsparticles->getParticles(); - - auto& halfEdge = (*zsparticles)[ZenoParticles::s_surfHalfEdgeTag]; - halfEdge = typename ZenoParticles::particles_t({{"local_vertex_id",1},{"to_face",1},{"opposite_he",1},{"next_he",1}}, - tris.size() * 3,zs::memsrc_e::device,0); + if(!zsparticles->hasAuxData(ZenoParticles::s_surfTriTag) && zsparticles->category == ZenoParticles::category_e::tet) + throw std::runtime_error("the input tet zsparticles has no surface tris"); + // if(!zsparticles->hasAuxData(ZenoParticles::s_surfEdgeTag)) + // throw std::runtime_error("the input zsparticles has no surface lines"); + if(!zsparticles->hasAuxData(ZenoParticles::s_surfVertTag) && zsparticles->category == ZenoParticles::category_e::tet) + throw std::runtime_error("the input tet zsparticles has no surface points"); + + auto& tris = zsparticles->category == ZenoParticles::category_e::tet ? (*zsparticles)[ZenoParticles::s_surfTriTag] : zsparticles->getQuadraturePoints(); + // auto& lines = (*zsparticles)[ZenoParticles::s_surfEdgeTag]; + auto& points = zsparticles->category == ZenoParticles::category_e::tet ? (*zsparticles)[ZenoParticles::s_surfVertTag] : zsparticles->getParticles(); + + auto& halfEdge = (*zsparticles)[ZenoParticles::s_surfHalfEdgeTag]; + halfEdge = typename ZenoParticles::particles_t({{"local_vertex_id",1},{"to_face",1},{"opposite_he",1},{"next_he",1}}, + tris.size() * 3,zs::memsrc_e::device,0); - auto cudaPol = zs::cuda_exec(); + auto cudaPol = zs::cuda_exec(); - points.append_channels(cudaPol,{{"he_inds",1}}); - // lines.append_channels(cudaPol,{{"he_inds",1}}); - tris.append_channels(cudaPol,{{"he_inds",1}}); + points.append_channels(cudaPol,{{"he_inds",1}}); + // lines.append_channels(cudaPol,{{"he_inds",1}}); + tris.append_channels(cudaPol,{{"he_inds",1}}); #if 0 - constexpr auto space = zs::execspace_e::cuda; - - TILEVEC_OPS::fill(cudaPol,halfEdge,"to_vertex",reinterpret_bits((int)-1)); - TILEVEC_OPS::fill(cudaPol,halfEdge,"to_face",reinterpret_bits((int)-1)); - TILEVEC_OPS::fill(cudaPol,halfEdge,"to_edge",reinterpret_bits((int)-1)); - TILEVEC_OPS::fill(cudaPol,halfEdge,"opposite_he",reinterpret_bits((int)-1)); - TILEVEC_OPS::fill(cudaPol,halfEdge,"next_he",reinterpret_bits((int)-1)); - - // we might also need a space hash structure here, map from [i1,i2]->[ej] - bcht,32> de2fi{halfEdge.get_allocator(),halfEdge.size()}; - - cudaPol(zs::range(tris.size()), [ - tris = proxy({},tris),de2fi = proxy(de2fi),halfEdge = proxy({},halfEdge)] ZS_LAMBDA(int ti) mutable { - auto fe_inds = tris.pack(dim_c<3>,"fe_inds",ti).reinterpret_bits(int_c); - auto tri = tris.pack(dim_c<3>,"inds",ti).reinterpret_bits(int_c); - - vec3i nos{}; - for(int i = 0;i != 3;++i) { - if(auto no = de2fi.insert(vec2i{tri[i],tri[(i+1) % 3]});no >= 0){ - nos[i] = no; - halfEdge("to_vertex",no) = reinterpret_bits(tri[i]); - halfEdge("to_face",no) = reinterpret_bits(ti); - halfEdge("to_edge",no) = reinterpret_bits(fe_inds[i]); - // halfEdge("next_he",no) = ti * 3 + (i+1) % 3; - } else { - // some error happen - - } - } - for(int i = 0;i != 3;++i) - halfEdge("next_he",nos[i]) = reinterpret_bits(nos[(i+1) % 3]); - }); - cudaPol(zs::range(halfEdge.size()), - [halfEdge = proxy({},halfEdge),de2fi = proxy(de2fi)] ZS_LAMBDA(int hei) mutable { - auto idx0 = reinterpret_bits(halfEdge("to_vertex",hei)); - auto nexthei = reinterpret_bits(halfEdge("next_he",hei)); - auto idx1 = reinterpret_bits(halfEdge("to_vertex",nexthei)); - if(auto no = de2fi.query(vec2i{idx1,idx0});no >= 0) - halfEdge("opposite_he",hei) = reinterpret_bits(no); - else - halfEdge("opposite_he",hei) = reinterpret_bits((int)-1); - }); + // constexpr auto space = zs::execspace_e::cuda; + + TILEVEC_OPS::fill(cudaPol,halfEdge,"to_vertex",reinterpret_bits((int)-1)); + TILEVEC_OPS::fill(cudaPol,halfEdge,"to_face",reinterpret_bits((int)-1)); + TILEVEC_OPS::fill(cudaPol,halfEdge,"to_edge",reinterpret_bits((int)-1)); + TILEVEC_OPS::fill(cudaPol,halfEdge,"opposite_he",reinterpret_bits((int)-1)); + TILEVEC_OPS::fill(cudaPol,halfEdge,"next_he",reinterpret_bits((int)-1)); + + // we might also need a space hash structure here, map from [i1,i2]->[ej] + bcht,32> de2fi{halfEdge.get_allocator(),halfEdge.size()}; + + cudaPol(zs::range(tris.size()), [ + tris = proxy({},tris),de2fi = proxy(de2fi),halfEdge = proxy({},halfEdge)] ZS_LAMBDA(int ti) mutable { + auto fe_inds = tris.pack(dim_c<3>,"fe_inds",ti).reinterpret_bits(int_c); + auto tri = tris.pack(dim_c<3>,"inds",ti).reinterpret_bits(int_c); + + vec3i nos{}; + for(int i = 0;i != 3;++i) { + if(auto no = de2fi.insert(vec2i{tri[i],tri[(i+1) % 3]});no >= 0){ + nos[i] = no; + halfEdge("to_vertex",no) = reinterpret_bits(tri[i]); + halfEdge("to_face",no) = reinterpret_bits(ti); + halfEdge("to_edge",no) = reinterpret_bits(fe_inds[i]); + // halfEdge("next_he",no) = ti * 3 + (i+1) % 3; + } else { + // some error happen + + } + } + for(int i = 0;i != 3;++i) + halfEdge("next_he",nos[i]) = reinterpret_bits(nos[(i+1) % 3]); + }); + cudaPol(zs::range(halfEdge.size()), + [halfEdge = proxy({},halfEdge),de2fi = proxy(de2fi)] ZS_LAMBDA(int hei) mutable { + auto idx0 = reinterpret_bits(halfEdge("to_vertex",hei)); + auto nexthei = reinterpret_bits(halfEdge("next_he",hei)); + auto idx1 = reinterpret_bits(halfEdge("to_vertex",nexthei)); + if(auto no = de2fi.query(vec2i{idx1,idx0});no >= 0) + halfEdge("opposite_he",hei) = reinterpret_bits(no); + else + halfEdge("opposite_he",hei) = reinterpret_bits((int)-1); + }); - points.append_channels(cudaPol,{{"he_inds",1}}); - lines.append_channels(cudaPol,{{"he_inds",1}}); - tris.append_channels(cudaPol,{{"he_inds",1}}); + points.append_channels(cudaPol,{{"he_inds",1}}); + lines.append_channels(cudaPol,{{"he_inds",1}}); + tris.append_channels(cudaPol,{{"he_inds",1}}); + + cudaPol(zs::range(lines.size()),[ + lines = proxy({},lines),de2fi = proxy(de2fi)] ZS_LAMBDA(int li) mutable { + auto linds = lines.pack(dim_c<2>,"inds",li).reinterpret_bits(int_c); + if(auto no = de2fi.query(vec2i{linds[0],linds[1]});no >= 0){ + lines("he_inds",li) = reinterpret_bits((int)no); + }else { + // some algorithm bug + } + }); - cudaPol(zs::range(lines.size()),[ - lines = proxy({},lines),de2fi = proxy(de2fi)] ZS_LAMBDA(int li) mutable { - auto linds = lines.pack(dim_c<2>,"inds",li).reinterpret_bits(int_c); - if(auto no = de2fi.query(vec2i{linds[0],linds[1]});no >= 0){ - lines("he_inds",li) = reinterpret_bits((int)no); - }else { - // some algorithm bug - } - }); + if(!tris.hasProperty("fp_inds") || tris.getPropertySize("fp_inds") != 3) { + throw std::runtime_error("the tris has no fp_inds channel"); + } - if(!tris.hasProperty("fp_inds") || tris.getPropertySize("fp_inds") != 3) { - throw std::runtime_error("the tris has no fp_inds channel"); - } + cudaPol(zs::range(tris.size()),[ + tris = proxy({},tris),de2fi = proxy(de2fi)] ZS_LAMBDA(int ti) mutable { - cudaPol(zs::range(tris.size()),[ - tris = proxy({},tris),de2fi = proxy(de2fi)] ZS_LAMBDA(int ti) mutable { + auto tri = tris.pack(dim_c<3>,"inds",ti).reinterpret_bits(int_c); + if(auto no = de2fi.query(vec2i{tri[0],tri[1]});no >= 0){ + tris("he_inds",ti) = reinterpret_bits((int)no); + }else { + // some algorithm bug + printf("could not find half edge : %d %d\n",tri[0],tri[1]); + } + // auto tinds = tris.pack(dim_c<3>,"fp_inds",ti).reinterpret_bits(int_c); + // for(int i = 0;i != 3;++i) { + // if(auto no = de2fi.query(vec2i{tri[i],tri[(i+1) % 3]});no >= 0){ + // points("he_inds",tinds[i]) = reinterpret_bits((int)no); + // }else { + // // some algorithm bug + // printf("could not find half edge : %d %d\n",tri[i],tri[(i+1) % 3]); + // } + // } + }); - auto tri = tris.pack(dim_c<3>,"inds",ti).reinterpret_bits(int_c); - if(auto no = de2fi.query(vec2i{tri[0],tri[1]});no >= 0){ - tris("he_inds",ti) = reinterpret_bits((int)no); + cudaPol(zs::range(tris.size()),[ + points = proxy({},points),tris = proxy({},tris),de2fi = proxy(de2fi)] ZS_LAMBDA(int ti) mutable { + auto tinds = tris.pack(dim_c<3>,"fp_inds",ti).reinterpret_bits(int_c); + auto tri = tris.pack(dim_c<3>,"inds",ti).reinterpret_bits(int_c); + for(int i = 0;i != 3;++i) { + if(auto no = de2fi.query(vec2i{tri[i],tri[(i+1) % 3]});no >= 0){ + points("he_inds",tinds[i]) = reinterpret_bits((int)no); }else { // some algorithm bug - printf("could not find half edge : %d %d\n",tri[0],tri[1]); - } - // auto tinds = tris.pack(dim_c<3>,"fp_inds",ti).reinterpret_bits(int_c); - // for(int i = 0;i != 3;++i) { - // if(auto no = de2fi.query(vec2i{tri[i],tri[(i+1) % 3]});no >= 0){ - // points("he_inds",tinds[i]) = reinterpret_bits((int)no); - // }else { - // // some algorithm bug - // printf("could not find half edge : %d %d\n",tri[i],tri[(i+1) % 3]); - // } - // } - }); - - cudaPol(zs::range(tris.size()),[ - points = proxy({},points),tris = proxy({},tris),de2fi = proxy(de2fi)] ZS_LAMBDA(int ti) mutable { - auto tinds = tris.pack(dim_c<3>,"fp_inds",ti).reinterpret_bits(int_c); - auto tri = tris.pack(dim_c<3>,"inds",ti).reinterpret_bits(int_c); - for(int i = 0;i != 3;++i) { - if(auto no = de2fi.query(vec2i{tri[i],tri[(i+1) % 3]});no >= 0){ - points("he_inds",tinds[i]) = reinterpret_bits((int)no); - }else { - // some algorithm bug - printf("could not find half edge : %d %d\n",tri[i],tri[(i+1) % 3]); - } - } - }); + printf("could not find half edge : %d %d\n",tri[i],tri[(i+1) % 3]); + } + } + }); #else - if(!build_surf_half_edge(cudaPol,tris,points,halfEdge)) - throw std::runtime_error("fail building surf half edge"); + if(!build_surf_half_edge(cudaPol,tris,points,halfEdge)) + throw std::runtime_error("fail building surf half edge"); #endif - set_output("zsparticles",zsparticles); - // zsparticles->setMeta("de2fi",std::move()) + zs::bht edgeSet{tris.get_allocator(),tris.size() * 3}; + edgeSet.reset(cudaPol,true); + cudaPol(zs::range(halfEdge.size()),[ + halfedges = proxy({},halfEdge), + edgeSet = proxy(edgeSet), + tris = proxy({},tris)] ZS_LAMBDA(int hi) mutable { + auto ti = zs::reinterpret_bits(halfedges("to_face",hi)); + auto tri = tris.pack(dim_c<3>,"inds",ti,int_c); + auto local_idx = zs::reinterpret_bits(halfedges("local_vertex_id",hi)); + zs::vec edge{tri[local_idx],tri[(local_idx + 1) % 3]}; + + auto ohi = zs::reinterpret_bits(halfedges("opposite_he",hi)); + if(ohi >= 0 && edge[0] > edge[1]) + return; + + edgeSet.insert(hi); + }); + + auto &surfEdges = (*zsparticles)[ZenoParticles::s_surfEdgeTag]; + surfEdges = typename ZenoParticles::particles_t({{"inds", 2},{"he_inds",1}}, edgeSet.size(),zs::memsrc_e::device,0); + cudaPol(zip(zs::range(edgeSet.size()),edgeSet._activeKeys),[ + halfedges = proxy({},halfEdge), + surfEdges = proxy({},surfEdges), + tris = proxy({},tris)] ZS_LAMBDA(auto ei,const auto& hi_vec) mutable { + auto hi = hi_vec[0]; + auto ti = zs::reinterpret_bits(halfedges("to_face",hi)); + auto tri = tris.pack(dim_c<3>,"inds",ti,int_c); + auto local_idx = zs::reinterpret_bits(halfedges("local_vertex_id",hi)); + zs::vec edge{tri[local_idx],tri[(local_idx + 1) % 3]}; + + surfEdges.tuple(dim_c<2>,"inds",ei) = edge.reinterpret_bits(float_c); + surfEdges("he_inds",ei) = reinterpret_bits((int)hi); + }); + + set_output("zsparticles",zsparticles); + // zsparticles->setMeta("de2fi",std::move()) } }; @@ -167,6 +202,7 @@ struct BuildTetrahedraHalfFacet : zeno::INode { using namespace zs; auto cudaPol = zs::cuda_exec(); + auto zsparticles = get_input("zsparticles"); auto& tets = zsparticles->getQuadraturePoints(); @@ -187,6 +223,51 @@ ZENDEFNODE(BuildTetrahedraHalfFacet, {{{"zsparticles"}}, {}, {"ZSGeometry"}}); +struct BuildSurfaceLinesStructure : zeno::INode { + using T = float; + virtual void apply() override { + using namespace zs; + using vec2i = zs::vec; + using vec3i = zs::vec; + auto cudaPol = zs::cuda_exec(); + constexpr auto space = zs::execspace_e::cuda; + + auto zsparticles = get_input("zsparticles"); + if(!zsparticles->hasAuxData(ZenoParticles::s_surfTriTag) && zsparticles->category == ZenoParticles::category_e::tet) + throw std::runtime_error("the input tet zsparticles has no surface tris"); + + auto& tris = zsparticles->category == ZenoParticles::category_e::tet ? (*zsparticles)[ZenoParticles::s_surfTriTag] : zsparticles->getQuadraturePoints(); + zs::bht edgeSet{tris.get_allocator(),tris.size() * 3}; + edgeSet.reset(cudaPol,true); + + cudaPol(zs::range(tris.size()),[ + tris = proxy({},tris), + edgeSet = proxy(edgeSet)] ZS_LAMBDA(int ti) mutable { + auto tri = tris.pack(dim_c<3>,"inds",ti,int_c); + for(int i = 0;i != 3;++i) { + auto idx0 = tri[(i + 0) % 3]; + auto idx1 = tri[(i + 1) % 3]; + if(idx0 < idx1) + edgeSet.insert(vec2i{idx0,idx1}); + } + }); + + auto &surfEdges = (*zsparticles)[ZenoParticles::s_surfEdgeTag]; + surfEdges = typename ZenoParticles::particles_t({{"inds", 2}}, edgeSet.size(),zs::memsrc_e::device,0); + cudaPol(zip(zs::range(edgeSet.size()),edgeSet._activeKeys),[ + surfEdges = proxy({},surfEdges)] ZS_LAMBDA(auto ei,const auto& pair) mutable { + surfEdges.tuple(dim_c<2>,"inds",ei) = pair.reinterpret_bits(float_c); + }); + + set_output("zsparticles",zsparticles); + } +}; + +ZENDEFNODE(BuildSurfaceLinesStructure, {{{"zsparticles"}}, + {{"zsparticles"}}, + {}, + {"ZSGeometry"}}); + struct VisualTetrahedraHalfFacet : zeno::INode { using T = float; // using dtiles_t = zs::TileVector; @@ -698,13 +779,15 @@ struct DoTopogicalColoring : zeno::INode { constexpr auto space = zs::execspace_e::cuda; auto zsparticles = get_input("zsparticles"); - const auto& verts = zsparticles->getParticles(); + // const auto& verts = zsparticles->getParticles(); auto& elms = zsparticles->getQuadraturePoints(); // auto& tris = (*zsparticles)[ZenoParticles::s_surfTriTag]; // const auto& tets = zsparticles->getQuadraturePoints(); auto cdim = elms.getPropertySize("inds"); auto color_tag = get_param("colorTag"); + auto do_sort_color = get_param("sort_color"); + if(!elms.hasProperty(color_tag)) elms.append_channels(cudaPol,{{color_tag,1}}); @@ -720,17 +803,33 @@ struct DoTopogicalColoring : zeno::INode { }); zs::Vector colors{elms.get_allocator(),elms.size()}; - std::cout << "do topological coloring" << std::endl; + // std::cout << "do topological coloring" << std::endl; topological_coloring(cudaPol,topos,colors); - std::cout << "finish topological coloring" << std::endl; + zs::Vector reordered_map{elms.get_allocator(),elms.size()}; + cudaPol(zs::range(reordered_map.size()),[reordered_map = proxy(reordered_map)] ZS_LAMBDA(int ti) mutable {reordered_map[ti] = ti;}); + // if(do_sort_color) + zs::Vector color_offset{elms.get_allocator(),0}; + sort_topology_by_coloring_tag(cudaPol,colors,reordered_map,color_offset); + + // std::cout << "finish topological coloring" << std::endl; cudaPol(zs::range(elms.size()),[ elms = proxy({},elms), color_tag = zs::SmallString(color_tag), + topos = proxy(topos), + reordered_map = proxy(reordered_map), + cdim, colors = proxy(colors)] ZS_LAMBDA(int ei) mutable { - elms(color_tag,ei) = colors[ei]; + elms(color_tag,ei) = colors[reordered_map[ei]]; + for(int i = 0;i != cdim;++i) + elms("inds",i,ei) = zs::reinterpret_bits(topos[reordered_map[ei]][i]); }); + zsparticles->setMeta("color_offset",color_offset); + printf("offset : "); + for(int i = 0;i != color_offset.size();++i) + printf("%d\t",color_offset.getVal(i)); + printf("\n"); set_output("zsparticles",zsparticles); } }; @@ -740,7 +839,8 @@ ZENDEFNODE(DoTopogicalColoring, {{{"zsparticles"}}, {"zsparticles"} }, { - {"string","colorTag","colorTag"} + {"string","colorTag","colorTag"}, + // {"bool","sort_color","1"} }, {"ZSGeometry"}}); diff --git a/projects/CuLagrange/geometry/file_parser/read_vtk_mesh.hpp b/projects/CuLagrange/geometry/file_parser/read_vtk_mesh.hpp index 00634c7f80..bc03a2fc2f 100644 --- a/projects/CuLagrange/geometry/file_parser/read_vtk_mesh.hpp +++ b/projects/CuLagrange/geometry/file_parser/read_vtk_mesh.hpp @@ -136,13 +136,13 @@ namespace zeno { return true; } - template - bool parsing_cells_topology(FILE* fp,typename zeno::AttrVector>& cells_attrv,int numberofcells,int &line_count) { + template + bool parsing_cells_topology(FILE* fp,PRIM_PTR prim,int numberofcells,int &line_count) { char *bufferp; char buffer[INPUTLINESIZE]; - cells_attrv.resize(numberofcells); - auto& cells = cells_attrv.values; + // cells_attrv.resize(numberofcells); + // auto& cells = cells_attrv.values; int nm_cells_read = 0; @@ -156,21 +156,28 @@ namespace zeno { return false; } int nn = strtol(bufferp,&bufferp,0); - if(nn != CELL_SIZE){ - printf("the size of cell(%d) does not match the target memory type(%d)\n",nn,CELL_SIZE); - printf("line : %s\n",bufferp); - fclose(fp); + if(nn == 3) { + prim->tris.resize(numberofcells); + } + else if(nn == 4) { + prim->quads.resize(numberofcells); + } + else { + printf("invalid dim of polygon %d, only tris and quads are currently supported\n",nn); return false; } - // printf("reading cell<%d> : ",nm_cells_read); - for(int j = 0;j != CELL_SIZE;++j){ + for(int j = 0;j != nn;++j){ if(*bufferp == '\0') { - printf("syntax error reading vertex coords on line %d parsing cells(%d)\n",line_count,CELL_SIZE); + printf("syntax error reading vertex coords on line %d parsing cells(%d)\n",line_count,nn); fclose(fp); return false; } bufferp = find_next_numeric(bufferp);// skip the header line idx, different index packs in different lines - cells[nm_cells_read][j] = (int)strtol(bufferp,&bufferp,0); + if(nn == 3) + prim->tris[nm_cells_read][j] = (int)strtol(bufferp,&bufferp,0); + else if(nn == 4) + prim->quads[nm_cells_read][j] = (int)strtol(bufferp,&bufferp,0); + // printf("%d\t",cells[nm_cells_read][j]); } // printf("\n"); @@ -495,7 +502,7 @@ namespace zeno { int numberoflines = 0; printf("reading lines\n"); sscanf(line,"%s %d %d",id,&numberoflines,&dummy); - if(!parsing_cells_topology<2>(fp,prim->lines,numberoflines,line_count)) + if(!parsing_cells_topology(fp,prim,numberoflines,line_count)) return false; printf("finish reading lines\n"); continue; @@ -506,7 +513,7 @@ namespace zeno { sscanf(line,"%s %d %d",id,&numberofpolys,&dummy); printf("readling polygons %s %d %d\n",id,numberofpolys,dummy); - if(!parsing_cells_topology<3>(fp,prim->tris,numberofpolys,line_count)) + if(!parsing_cells_topology(fp,prim,numberofpolys,line_count)) return false; printf("finish reading polygons\n"); continue; @@ -611,9 +618,9 @@ namespace zeno { simplex_size = numberofdofs/numberofcells - 1; printf("simplex_size %d\n",simplex_size); if(simplex_size == 4) - parsing_cells_topology<4>(fp,prim->quads,numberofcells,line_count); + parsing_cells_topology(fp,prim,numberofcells,line_count); else if(simplex_size == 3) - parsing_cells_topology<3>(fp,prim->tris,numberofcells,line_count); + parsing_cells_topology(fp,prim,numberofcells,line_count); else { printf("invalid simplex size = %d %d %d\n",simplex_size,numberofcells,numberofdofs); throw std::runtime_error("INVALID SIMPLEX SIZE"); diff --git a/projects/CuLagrange/geometry/kernel/geo_math.hpp b/projects/CuLagrange/geometry/kernel/geo_math.hpp index 6fc9fc6c0d..3c0513ad58 100644 --- a/projects/CuLagrange/geometry/kernel/geo_math.hpp +++ b/projects/CuLagrange/geometry/kernel/geo_math.hpp @@ -43,6 +43,22 @@ namespace zeno { namespace LSL_GEO { return doublearea(a,b,c) / (typename VecT::value_type)2.0; } + template 1)> = 0> + constexpr auto cotTheta(const zs::VecInterface& e0,const zs::VecInterface& e1){ + auto costheta = e0.dot(e1); + auto sintheta = e0.cross(e1).norm(); + return (costheta / sintheta); + } + + template 1)> = 0,typename REAL = VecT::value_type> + constexpr auto cotTheta(const zs::VecInterface& e0,const zs::VecInterface& e1){ + auto de0 = e0.cast(); + auto de1 = e1.cast(); + auto costheta = de0.dot(de1); + auto sintheta = de0.cross(de1).norm(); + return (REAL)(costheta / sintheta); + } + template 1)> = 0> constexpr int orient(const zs::VecInterface& p0, const zs::VecInterface& p1, @@ -613,6 +629,19 @@ constexpr REAL pointTriangleDistance(const VECTOR3& v0, const VECTOR3& v1, } + constexpr void pointBaryCentric(const VECTOR3& v0, const VECTOR3& v1, + const VECTOR3& v2, const VECTOR3& v,VECTOR3& bary) { + const VECTOR3 e1 = v1 - v0; + const VECTOR3 e2 = v2 - v0; + const VECTOR3 n = e1.cross(e2); + const VECTOR3 na = (v2 - v1).cross(v - v1); + const VECTOR3 nb = (v0 - v2).cross(v - v2); + const VECTOR3 nc = (v1 - v0).cross(v - v0); + const VECTOR3 barycentric(n.dot(na) / n.l2NormSqr(), + n.dot(nb) / n.l2NormSqr(), + n.dot(nc) / n.l2NormSqr()); + bary = barycentric; + } constexpr REAL pointTriangleDistance(const VECTOR3& v0, const VECTOR3& v1, const VECTOR3& v2, const VECTOR3& v,REAL& barySum) @@ -831,5 +860,40 @@ constexpr REAL pointTriangleDistance(const VECTOR3& v0, const VECTOR3& v1, } return std::numeric_limits::infinity(); } + + constexpr REAL ray_ray_intersect(VECTOR3 const& x0,VECTOR3 const& v0,VECTOR3 const &x1,VECTOR3 const& v1,REAL thickness) { + auto x = x1 - x0; + auto v = v1 - v0; + + if(x.norm() < thickness && x.dot(v) > 0) + return std::numeric_limits::infinity(); + if(x.norm() < thickness && x.dot(v) < 0) + return (REAL)0; + // if(vv.norm() < 1e) + + auto xx = x.dot(x); + auto vv = v.dot(v); + auto xv = x.dot(v); + + // auto closest_dist = (x - xv / vv * v).norm(); + // if(closest_dist > thickness) + // return std::numeric_limits::infinity(); + + auto delta = 4 * xv * xv - 4 * vv * (xx - thickness * thickness); + if(delta < 0) + return std::numeric_limits::infinity(); + + auto sqrt_delta = zs::sqrt(delta); + auto alpha = xv / vv; + auto beta = sqrt_delta / 2 / vv; + + auto t0 = alpha + beta; + auto t1 = alpha - beta; + + t0 = t0 < (REAL)1.0 && t0 > (REAL)0.0 ? t0 : std::numeric_limits::infinity(); + t1 = t1 < (REAL)1.0 && t1 > (REAL)0.0 ? t1 : std::numeric_limits::infinity(); + + return zs::min(t0,t1); + } }; }; \ No newline at end of file diff --git a/projects/CuLagrange/geometry/kernel/intersection.hpp b/projects/CuLagrange/geometry/kernel/intersection.hpp index ba17ace0aa..a82b66786e 100644 --- a/projects/CuLagrange/geometry/kernel/intersection.hpp +++ b/projects/CuLagrange/geometry/kernel/intersection.hpp @@ -1796,14 +1796,14 @@ int do_global_self_intersection_analysis_on_surface_mesh_info(Pol& pol, vec3 v1[3] = {}; vec3 e0s[3] = {}; vec3 e1s[3] = {}; - for(int i = 0;i != 3;++i) { - v0[i] = verts.pack(dim_c<3>,xtag,tri_t0[i]); - v1[i] = verts.pack(dim_c<3>,xtag,tri_t1[i]); + for(int j = 0;j != 3;++j) { + v0[j] = verts.pack(dim_c<3>,xtag,tri_t0[j]); + v1[j] = verts.pack(dim_c<3>,xtag,tri_t1[j]); } - for(int i = 0;i != 3;++i) { - e0s[i] = v0[(i + 1) % 3] - v0[i]; - e1s[i] = v1[(i + 1) % 3] - v1[i]; + for(int j = 0;j != 3;++j) { + e0s[j] = v0[(j + 1) % 3] - v0[j]; + e1s[j] = v1[(j + 1) % 3] - v1[j]; } auto nrm0 = (v0[1] - v0[0]).cross(v0[2] - v0[0]).normalized(); @@ -1926,9 +1926,9 @@ int do_global_self_intersection_analysis_on_surface_mesh_info(Pol& pol, vec3 v1[3] = {}; vec3 e0s[3] = {}; vec3 e1s[3] = {}; - for(int i = 0;i != 3;++i) { - v0[i] = verts.pack(dim_c<3>,xtag,tri_t0[i]); - v1[i] = verts.pack(dim_c<3>,xtag,tri_t1[i]); + for(int j = 0;j != 3;++j) { + v0[j] = verts.pack(dim_c<3>,xtag,tri_t0[j]); + v1[j] = verts.pack(dim_c<3>,xtag,tri_t1[j]); } for(int i = 0;i != 3;++i) { diff --git a/projects/CuLagrange/geometry/kernel/topology.hpp b/projects/CuLagrange/geometry/kernel/topology.hpp index 6f993ca80c..843185142e 100644 --- a/projects/CuLagrange/geometry/kernel/topology.hpp +++ b/projects/CuLagrange/geometry/kernel/topology.hpp @@ -843,12 +843,12 @@ namespace zeno { tet[facet_indices[i * 3 + 2]]}; int min_idx = 0; int min_id = facet[i]; - for(int i = 1;i != 3;++i) - if(facet[i] < min_id){ - min_idx = i; - min_id = facet[i]; + for(int j = 1;j != 3;++j) + if(facet[j] < min_id){ + min_idx = j; + min_id = facet[j]; } - for(int i = 0;i != min_idx;++i) { + for(int j = 0;j != min_idx;++j) { auto tmp = facet[0]; facet[0] = facet[1]; facet[1] = facet[2]; @@ -1256,18 +1256,22 @@ namespace zeno { constexpr auto space = Pol::exec_tag::value; using Ti = RM_CVREF_T(colors[0]); + std::cout << "do coloring " << std::endl; + colors.resize(topo.size()); zs::SparseMatrix topo_incidence_matrix{topo.get_allocator(),(int)topo.size(),(int)topo.size()}; - // std::cout << "compute incidence matrix " << std::endl; + std::cout << "compute incidence matrix " << std::endl; + + topological_incidence_matrix(pol,topo,topo_incidence_matrix); - // std::cout << "finish compute incidence matrix " << std::endl; + std::cout << "finish compute incidence matrix " << std::endl; auto ompPol = omp_exec(); constexpr auto omp_space = execspace_e::openmp; zs::Vector weights(/*topo.get_allocator(),*/topo.size()); { - bht tab{weights.get_allocator(),topo.size() * 2}; + bht tab{weights.get_allocator(),topo.size() * 100}; tab.reset(ompPol, true); ompPol(enumerate(weights), [tab1 = proxy(tab)] (int seed, u32 &w) mutable { using tab_t = RM_CVREF_T(tab); @@ -1285,7 +1289,7 @@ namespace zeno { weights = weights.clone(colors.memoryLocation()); // for(int i = 0;i != weights.size();++i) // printf("w[%d] : %u\n",i,weights.getVal(i)); - + std::cout << "do maximum set " << std::endl; auto iterRef = maximum_independent_sets(pol, topo_incidence_matrix, weights, colors); std::cout << "nm_colors : " << iterRef << std::endl; pol(zs::range(colors),[] ZS_LAMBDA(auto& clr) mutable {clr = clr - (Ti)1;}); @@ -1314,7 +1318,7 @@ namespace zeno { atomic_max(exec_tag,&max_color[0],color); }); - int nm_total_colors = max_color.getVal(0) + 1; + size_t nm_total_colors = max_color.getVal(0) + 1; // zs::bht color_buffer{} zs::Vector nm_colors{colors.get_allocator(),nm_total_colors}; pol(zs::range(nm_colors),[] ZS_LAMBDA(auto& nclr) mutable {nclr = 0;}); @@ -1365,6 +1369,7 @@ namespace zeno { return out_topo; } + // the topos: triA: [idx0,idx2,idx3] triB: [idx1,idx3,idx2] template void retrieve_tri_bending_topology(Pol& pol, const TriTileVec& tris, @@ -1406,7 +1411,8 @@ namespace zeno { auto tri = tris.pack(dim_c<3>,"inds",ti,int_c); auto otri = tris.pack(dim_c<3>,"inds",oti,int_c); - tb_topos[id] = zs::vec(tri[(vid + 0) % 3],tri[(vid + 1) % 3],tri[(vid + 2) % 3],otri[(ovid + 2) % 3]); + // tb_topos[id] = zs::vec(tri[(vid + 0) % 3],tri[(vid + 1) % 3],tri[(vid + 2) % 3],otri[(ovid + 2) % 3]); + tb_topos[id] = zs::vec(tri[(vid + 2) % 3],otri[(ovid + 2) % 3],tri[(vid + 0) % 3],tri[(vid + 1) % 3]); }); } diff --git a/projects/CuLagrange/geometry/linear_system/mfcg.hpp b/projects/CuLagrange/geometry/linear_system/mfcg.hpp index b0eb3045ac..806ffb0a0a 100644 --- a/projects/CuLagrange/geometry/linear_system/mfcg.hpp +++ b/projects/CuLagrange/geometry/linear_system/mfcg.hpp @@ -738,8 +738,8 @@ if(do_cuda_profile) auto rn = TILEVEC_OPS::dot<3>(cudaPol,vtemp,"r","r"); auto qn = TILEVEC_OPS::dot<3>(cudaPol,vtemp,"q","q"); auto Pn = TILEVEC_OPS::dot<9>(cudaPol,vtemp,"P","P"); - auto bn = TILEVEC_OPS::dot<3>(cudaPol,vtemp,"b","b"); - auto xn = TILEVEC_OPS::dot<3>(cudaPol,vtemp,"x","x"); + auto bn = TILEVEC_OPS::dot<3>(cudaPol,vert_buffer,btag,btag); + auto xn = TILEVEC_OPS::dot<3>(cudaPol,vert_buffer,xtag,xtag); auto tempn = TILEVEC_OPS::dot<3>(cudaPol,vtemp,"temp","temp"); fmt::print(fg(fmt::color::dark_cyan),"nan zTrk detected = {} qn = {} rn = {} Pn = {} bn = {} tempn = {} xn = {}\n",zTrk,qn,rn,Pn,bn,tempn,xn); throw std::runtime_error("nan zTrk detected"); diff --git a/projects/CuLagrange/pbd/Constraints.cu b/projects/CuLagrange/pbd/Constraints.cu new file mode 100644 index 0000000000..1e3b501069 --- /dev/null +++ b/projects/CuLagrange/pbd/Constraints.cu @@ -0,0 +1,753 @@ +#include "Structures.hpp" +#include "zensim/Logger.hpp" +#include "zensim/cuda/execution/ExecutionPolicy.cuh" +#include "zensim/omp/execution/ExecutionPolicy.hpp" +#include "zensim/io/MeshIO.hpp" +#include "zensim/math/bit/Bits.h" +#include "zensim/types/Property.h" +#include +#include +#include +#include +#include +#include + +#include "constraint_function_kernel/constraint.cuh" +#include "../geometry/kernel/tiled_vector_ops.hpp" +#include "../geometry/kernel/topology.hpp" +#include "../geometry/kernel/geo_math.hpp" +// #include "../fem/collision_energy/evaluate_collision.hpp" +#include "constraint_function_kernel/constraint_types.hpp" + +namespace zeno { + + +// we only need to record the topo here +// serve triangulate mesh or strands only currently +struct MakeSurfaceConstraintTopology : INode { + template + void buildBvh(zs::CudaExecutionPolicy &pol, + TileVecT &verts, + const zs::SmallString& srcTag, + const zs::SmallString& dstTag, + const zs::SmallString& pscaleTag, + ZenoLinearBvh::lbvh_t &bvh) { + using namespace zs; + using bv_t = typename ZenoLinearBvh::lbvh_t::Box; + constexpr auto space = execspace_e::cuda; + Vector bvs{verts.get_allocator(), verts.size()}; + pol(range(verts.size()), + [verts = proxy({}, verts), + bvs = proxy(bvs), + pscaleTag,srcTag,dstTag] ZS_LAMBDA(int vi) mutable { + auto src = verts.template pack<3>(srcTag, vi); + auto dst = verts.template pack<3>(dstTag, vi); + auto pscale = verts(pscaleTag,vi); + + bv_t bv{src,dst}; + bv._min -= pscale; + bv._max += pscale; + bvs[vi] = bv; + }); + bvh.build(pol, bvs); + } + + virtual void apply() override { + using namespace zs; + using namespace PBD_CONSTRAINT; + + using vec3 = zs::vec; + using vec2i = zs::vec; + using vec3i = zs::vec; + using vec4i = zs::vec; + using mat4 = zs::vec; + + constexpr auto space = execspace_e::cuda; + auto cudaPol = zs::cuda_exec(); + + auto source = get_input("source"); + auto constraint = std::make_shared(); + + auto type = get_input2("topo_type"); + + if(source->category != ZenoParticles::surface) + throw std::runtime_error("Try adding Constraint topology to non-surface ZenoParticles"); + + const auto& verts = source->getParticles(); + const auto& quads = source->getQuadraturePoints(); + + auto uniform_stiffness = get_input2("stiffness"); + + zs::Vector colors{quads.get_allocator(),0}; + zs::Vector reordered_map{quads.get_allocator(),0}; + zs::Vector color_offset{quads.get_allocator(),0}; + + constraint->sprayedOffset = 0; + constraint->elements = typename ZenoParticles::particles_t({{"stiffness",1},{"lambda",1},{"tclr",1}}, 0, zs::memsrc_e::device,0); + auto &eles = constraint->getQuadraturePoints(); + + if(type == "stretch") { + constraint->setMeta(CONSTRAINT_KEY,category_c::edge_length_constraint); + auto quads_vec = tilevec_topo_to_zsvec_topo(cudaPol,quads,wrapv<3>{}); + zs::Vector> edge_topos{quads.get_allocator(),0}; + retrieve_edges_topology(cudaPol,quads_vec,edge_topos); + eles.resize(edge_topos.size()); + + topological_coloring(cudaPol,edge_topos,colors); + sort_topology_by_coloring_tag(cudaPol,colors,reordered_map,color_offset); + // std::cout << "quads.size() = " << quads.size() << "\t" << "edge_topos.size() = " << edge_topos.size() << std::endl; + eles.append_channels(cudaPol,{{"inds",2},{"r",1}}); + + auto rest_scale = get_input2("rest_scale"); + + cudaPol(zs::range(eles.size()),[ + verts = proxy({},verts), + eles = proxy({},eles), + reordered_map = proxy(reordered_map), + uniform_stiffness = uniform_stiffness, + colors = proxy(colors), + rest_scale = rest_scale, + edge_topos = proxy(edge_topos)] ZS_LAMBDA(int oei) mutable { + auto ei = reordered_map[oei]; + eles.tuple(dim_c<2>,"inds",oei) = edge_topos[ei].reinterpret_bits(float_c); + vec3 x[2] = {}; + for(int i = 0;i != 2;++i) + x[i] = verts.pack(dim_c<3>,"x",edge_topos[ei][i]); + eles("r",oei) = (x[0] - x[1]).norm() * rest_scale; + }); + + } + + // angle on (p2, p3) between triangles (p0, p2, p3) and (p1, p3, p2) + if(type == "bending") { + constraint->setMeta(CONSTRAINT_KEY,category_c::isometric_bending_constraint); + // constraint->category = ZenoParticles::tri_bending_spring; + // constraint->sprayedOffset = 0; + + const auto& halfedges = (*source)[ZenoParticles::s_surfHalfEdgeTag]; + + zs::Vector> bd_topos{quads.get_allocator(),0}; + retrieve_tri_bending_topology(cudaPol,quads,halfedges,bd_topos); + + eles.resize(bd_topos.size()); + + topological_coloring(cudaPol,bd_topos,colors); + sort_topology_by_coloring_tag(cudaPol,colors,reordered_map,color_offset); + // std::cout << "quads.size() = " << quads.size() << "\t" << "edge_topos.size() = " << edge_topos.size() << std::endl; + + eles.append_channels(cudaPol,{{"inds",4},{"Q",4 * 4}}); + + // std::cout << "halfedges.size() = " << halfedges.size() << "\t" << "bd_topos.size() = " << bd_topos.size() << std::endl; + + cudaPol(zs::range(eles.size()),[ + eles = proxy({},eles), + bd_topos = proxy(bd_topos), + reordered_map = proxy(reordered_map), + verts = proxy({},verts)] ZS_LAMBDA(int oei) mutable { + auto ei = reordered_map[oei]; + // printf("bd_topos[%d] : %d %d %d %d\n",ei,bd_topos[ei][0],bd_topos[ei][1],bd_topos[ei][2],bd_topos[ei][3]); + eles.tuple(dim_c<4>,"inds",oei) = bd_topos[ei].reinterpret_bits(float_c); + vec3 x[4] = {}; + for(int i = 0;i != 4;++i) + x[i] = verts.pack(dim_c<3>,"x",bd_topos[ei][i]); + + mat4 Q = mat4::uniform(0); + CONSTRAINT::init_IsometricBendingConstraint(x[0],x[1],x[2],x[3],Q); + eles.tuple(dim_c<16>,"Q",oei) = Q; + }); + } + // angle on (p2, p3) between triangles (p0, p2, p3) and (p1, p3, p2) + if(type == "dihedral") { + constraint->setMeta(CONSTRAINT_KEY,category_c::dihedral_bending_constraint); + + const auto& halfedges = (*source)[ZenoParticles::s_surfHalfEdgeTag]; + + zs::Vector> bd_topos{quads.get_allocator(),0}; + retrieve_tri_bending_topology(cudaPol,quads,halfedges,bd_topos); + + eles.resize(bd_topos.size()); + + topological_coloring(cudaPol,bd_topos,colors); + sort_topology_by_coloring_tag(cudaPol,colors,reordered_map,color_offset); + // std::cout << "quads.size() = " << quads.size() << "\t" << "edge_topos.size() = " << edge_topos.size() << std::endl; + + eles.append_channels(cudaPol,{{"inds",4},{"ra",1}}); + + cudaPol(zs::range(eles.size()),[ + eles = proxy({},eles), + bd_topos = proxy(bd_topos), + reordered_map = proxy(reordered_map), + verts = proxy({},verts)] ZS_LAMBDA(int oei) mutable { + auto ei = reordered_map[oei]; + eles.tuple(dim_c<4>,"inds",oei) = bd_topos[ei].reinterpret_bits(float_c); + + vec3 x[4] = {}; + for(int i = 0;i != 4;++i) + x[i] = verts.pack(dim_c<3>,"x",bd_topos[ei][i]); + + float alpha{}; + CONSTRAINT::init_DihedralBendingConstraint(x[0],x[1],x[2],x[3],alpha); + eles("ra",oei) = alpha; + }); + } + if(type == "kcollision") { + using bv_t = typename ZenoLinearBvh::lbvh_t::Box; + + constraint->setMeta(CONSTRAINT_KEY,category_c::p_kp_collision_constraint); + auto target = get_input("target"); + + const auto& kverts = target->getParticles(); + ZenoLinearBvh::lbvh_t kbvh{}; + buildBvh(cudaPol,kverts,"px","x","pscale",kbvh); + + zs::bht csPP{verts.get_allocator(),verts.size()}; + csPP.reset(cudaPol,true); + + cudaPol(zs::range(verts.size()),[ + verts = proxy({},verts), + kverts = proxy({},kverts), + kbvh = proxy(kbvh), + csPP = proxy(csPP)] ZS_LAMBDA(int vi) mutable { + auto x = verts.pack(dim_c<3>,"x",vi); + auto px = verts.pack(dim_c<3>,"px",vi); + auto mx = (x + px) / (T)2.0; + auto pscale = verts("pscale",vi); + + auto radius = (mx - px).norm() + pscale * (T)2.0; + auto bv = bv_t{mx - radius,mx + radius}; + + int contact_kvi = -1; + T min_contact_time = std::numeric_limits::max(); + + auto process_ccd_collision = [&](int kvi) { + auto kpscale = kverts("pscale",kvi); + auto kx = kverts.pack(dim_c<3>,"x",kvi); + auto pkx = kx; + if(kverts.hasProperty("px")) + pkx = kverts.pack(dim_c<3>,"px",kvi); + + auto t = LSL_GEO::ray_ray_intersect(px,x - px,pkx,kx - pkx,(pscale + kpscale) * (T)2); + if(t < min_contact_time) { + min_contact_time = t; + contact_kvi = kvi; + } + }; + kbvh.iter_neighbors(bv,process_ccd_collision); + + if(contact_kvi >= 0) { + csPP.insert(vec2i{vi,contact_kvi}); + } + }); + + eles.resize(csPP.size()); + colors.resize(csPP.size()); + reordered_map.resize(csPP.size()); + + eles.append_channels(cudaPol,{{"inds",2}}); + cudaPol(zip(zs::range(csPP.size()),csPP._activeKeys),[ + eles = proxy({},eles), + colors = proxy(colors), + reordered_map = proxy(reordered_map)] ZS_LAMBDA(auto ei,const auto& pair) mutable { + eles.tuple(dim_c<2>,"inds",ei) = pair.reinterpret_bits(float_c); + colors[ei] = (T)0; + reordered_map[ei] = ei; + }); + + color_offset.resize(1); + color_offset.setVal(0); + } + + if(type == "attachment") { + using bv_t = typename ZenoLinearBvh::lbvh_t::Box; + + } + + cudaPol(zs::range(eles.size()),[ + eles = proxy({},eles), + uniform_stiffness = uniform_stiffness, + colors = proxy(colors), + // exec_tag, + reordered_map = proxy(reordered_map)] ZS_LAMBDA(int oei) mutable { + auto ei = reordered_map[oei]; + eles("lambda",oei) = 0.0; + eles("stiffness",oei) = uniform_stiffness; + eles("tclr",oei) = colors[ei]; + // auto + }); + + constraint->setMeta("color_offset",color_offset); + + // set_output("source",source); + set_output("constraint",constraint); + }; +}; + +ZENDEFNODE(MakeSurfaceConstraintTopology, {{ + {"source"}, + {"target"}, + {"float","stiffness","0.5"}, + {"string","topo_type","stretch"}, + {"float","rest_scale","1.0"} + }, + {{"constraint"}}, + { + // {"string","groupID",""}, + }, + {"PBD"}}); + + +struct VisualizePBDConstraint : INode { + using T = float; + using vec3 = zs::vec; + // using tiles_t = typename ZenoParticles::particles_t; + // using dtiles_t = zs::TileVector; + + virtual void apply() override { + using namespace zs; + using namespace PBD_CONSTRAINT; + + constexpr auto space = execspace_e::cuda; + auto cudaPol = cuda_exec(); + + auto zsparticles = get_input("zsparticles"); + auto constraints_ptr = get_input("constraints"); + + const auto& geo_verts = zsparticles->getParticles(); + const auto& constraints = constraints_ptr->getQuadraturePoints(); + + auto tclr_tag = get_param("tclrTag"); + + zs::Vector cvis{geo_verts.get_allocator(),constraints.getChannelSize("inds") * constraints.size()}; + zs::Vector cclrs{constraints.get_allocator(),constraints.size()}; + int cdim = constraints.getChannelSize("inds"); + cudaPol(zs::range(constraints.size()),[ + constraints = proxy({},constraints), + geo_verts = proxy({},geo_verts), + cclrs = proxy(cclrs), + tclr_tag = zs::SmallString(tclr_tag), + cdim = cdim, + cvis = proxy(cvis)] ZS_LAMBDA(int ci) mutable { + // auto cdim = constraints.propertySize("inds"); + for(int i = 0;i != cdim;++i) { + auto vi = zs::reinterpret_bits(constraints("inds",i,ci)); + cvis[ci * cdim + i] = geo_verts.pack(dim_c<3>,"x",vi); + } + cclrs[ci] = (int)constraints(tclr_tag,ci); + }); + + constexpr auto omp_space = execspace_e::openmp; + auto ompPol = omp_exec(); + + cvis = cvis.clone({zs::memsrc_e::host}); + cclrs = cclrs.clone({zs::memsrc_e::host}); + auto prim = std::make_shared(); + auto& pverts = prim->verts; + + auto constraint_type = constraints_ptr->readMeta(CONSTRAINT_KEY,wrapt{}); + + if(constraint_type == category_c::edge_length_constraint) { + pverts.resize(constraints.size() * 2); + auto& plines = prim->lines; + plines.resize(constraints.size()); + auto& tclrs = pverts.add_attr(tclr_tag); + auto& ltclrs = plines.add_attr(tclr_tag); + + ompPol(zs::range(constraints.size()),[ + <clrs,&pverts,&plines,&tclrs,cvis = proxy(cvis),cclrs = proxy(cclrs)] (int ci) mutable { + pverts[ci * 2 + 0] = cvis[ci * 2 + 0].to_array(); + pverts[ci * 2 + 1] = cvis[ci * 2 + 1].to_array(); + tclrs[ci * 2 + 0] = cclrs[ci]; + tclrs[ci * 2 + 1] = cclrs[ci]; + plines[ci] = zeno::vec2i{ci * 2 + 0,ci * 2 + 1}; + ltclrs[ci] = cclrs[ci]; + }); + }else if(constraint_type == category_c::isometric_bending_constraint || constraint_type == category_c::dihedral_bending_constraint) { + pverts.resize(constraints.size() * 2); + auto& plines = prim->lines; + plines.resize(constraints.size()); + auto& tclrs = pverts.add_attr(tclr_tag); + auto& ltclrs = plines.add_attr(tclr_tag); + + ompPol(zs::range(constraints.size()),[ + <clrs,&pverts,&plines,&tclrs,cvis = proxy(cvis),cclrs = proxy(cclrs)] (int ci) mutable { + zeno::vec3f cverts[4] = {}; + for(int i = 0;i != 4;++i) + cverts[i] = cvis[ci * 4 + i].to_array(); + + pverts[ci * 2 + 0] = (cverts[0] + cverts[2] + cverts[3]) / (T)3.0; + pverts[ci * 2 + 1] = (cverts[1] + cverts[2] + cverts[3]) / (T)3.0; + tclrs[ci * 2 + 0] = cclrs[ci]; + tclrs[ci * 2 + 1] = cclrs[ci]; + ltclrs[ci] = cclrs[ci]; + + plines[ci] = zeno::vec2i{ci * 2 + 0,ci * 2 + 1}; + }); + } + + set_output("prim",std::move(prim)); + } +}; + +ZENDEFNODE(VisualizePBDConstraint, {{{"zsparticles"},{"constraints"}}, + {{"prim"}}, + { + {"string","tclrTag","tclrTag"}, + }, + {"PBD"}}); + +// solve a specific type of constraint for one iterations +struct XPBDSolve : INode { + + virtual void apply() override { + using namespace zs; + using namespace PBD_CONSTRAINT; + + using vec3 = zs::vec; + using vec2i = zs::vec; + using vec3i = zs::vec; + using vec4i = zs::vec; + using mat4 = zs::vec; + + constexpr auto space = execspace_e::cuda; + auto cudaPol = cuda_exec(); + constexpr auto exec_tag = wrapv{}; + + auto zsparticles = get_input("zsparticles"); + auto constraints = get_input("constraints"); + + auto dt = get_input2("dt"); + auto ptag = get_param("ptag"); + + auto coffsets = constraints->readMeta("color_offset",zs::wrapt>{}); + int nm_group = coffsets.size(); + + auto& verts = zsparticles->getParticles(); + auto& cquads = constraints->getQuadraturePoints(); + auto category = constraints->readMeta(CONSTRAINT_KEY,wrapt{}); + auto target = get_input("target"); + const auto& kverts = target->getParticles(); + // zs::Vector pv_buffer{verts.get_allocator(),verts.size()}; + // zs::Vector total_ghost_impulse_X{verts.get_allocator(),1}; + // zs::Vector total_ghost_impulse_Y{verts.get_allocator(),1}; + // zs::Vector total_ghost_impulse_Z{verts.get_allocator(),1}; + + // std::cout << "SOVLE CONSTRAINT WITH GROUP : " << nm_group << "\t" << cquads.size() << std::endl; + + + + for(int g = 0;g != nm_group;++g) { + + auto coffset = coffsets.getVal(g); + int group_size = 0; + if(g == nm_group - 1) + group_size = cquads.size() - coffsets.getVal(g); + else + group_size = coffsets.getVal(g + 1) - coffsets.getVal(g); + + cudaPol(zs::range(group_size),[ + coffset, + verts = proxy({},verts), + category, + dt, + ptag = zs::SmallString(ptag), + kverts = proxy({},kverts), + cquads = proxy({},cquads)] ZS_LAMBDA(int gi) mutable { + float s = cquads("stiffness",coffset + gi); + float lambda = cquads("lambda",coffset + gi); + + if(category == category_c::edge_length_constraint) { + auto edge = cquads.pack(dim_c<2>,"inds",coffset + gi,int_c); + vec3 p0{},p1{}; + p0 = verts.pack(dim_c<3>,ptag,edge[0]); + p1 = verts.pack(dim_c<3>,ptag,edge[1]); + float minv0 = verts("minv",edge[0]); + float minv1 = verts("minv",edge[1]); + float r = cquads("r",coffset + gi); + + vec3 dp0{},dp1{}; + if(!CONSTRAINT::solve_DistanceConstraint( + p0,minv0, + p1,minv1, + r, + s, + dt, + lambda, + dp0,dp1)) + return; + + + verts.tuple(dim_c<3>,ptag,edge[0]) = p0 + dp0; + verts.tuple(dim_c<3>,ptag,edge[1]) = p1 + dp1; + } + if(category == category_c::isometric_bending_constraint) { + auto quad = cquads.pack(dim_c<4>,"inds",coffset + gi,int_c); + vec3 p[4] = {}; + float minv[4] = {}; + for(int i = 0;i != 4;++i) { + p[i] = verts.pack(dim_c<3>,ptag,quad[i]); + minv[i] = verts("minv",quad[i]); + } + + auto Q = cquads.pack(dim_c<4,4>,"Q",coffset + gi); + + vec3 dp[4] = {}; + if(!CONSTRAINT::solve_IsometricBendingConstraint( + p[0],minv[0], + p[1],minv[1], + p[2],minv[2], + p[3],minv[3], + Q, + s, + dt, + lambda, + dp[0],dp[1],dp[2],dp[3])) + return; + + for(int i = 0;i != 4;++i) { + // printf("dp[%d][%d] : %f %f %f %f\n",gi,i,s,(float)dp[i][0],(float)dp[i][1],(float)dp[i][2]); + verts.tuple(dim_c<3>,ptag,quad[i]) = p[i] + dp[i]; + } + } + + if(category == category_c::dihedral_bending_constraint) { + auto quad = cquads.pack(dim_c<4>,"inds",coffset + gi,int_c); + vec3 p[4] = {}; + float minv[4] = {}; + for(int i = 0;i != 4;++i) { + p[i] = verts.pack(dim_c<3>,ptag,quad[i]); + minv[i] = verts("minv",quad[i]); + } + + auto ra = cquads("ra",coffset + gi); + vec3 dp[4] = {}; + if(!CONSTRAINT::solve_DihedralConstraint( + p[0],minv[0], + p[1],minv[1], + p[2],minv[2], + p[3],minv[3], + ra, + s, + dt, + lambda, + dp[0],dp[1],dp[2],dp[3])) + return; + for(int i = 0;i != 4;++i) { + // printf("dp[%d][%d] : %f %f %f %f\n",gi,i,s,(float)dp[i][0],(float)dp[i][1],(float)dp[i][2]); + verts.tuple(dim_c<3>,ptag,quad[i]) = p[i] + dp[i]; + } + } + + if(category == category_c::p_kp_collision_constraint) { + auto quad = cquads.pack(dim_c<2>,"inds",coffset + gi,int_c); + + vec3 p = verts.pack(dim_c<3>,ptag,quad[0]); + vec3 kp = kverts.pack(dim_c<3>,"x",quad[1]); + vec3 knrm = kverts.pack(dim_c<3>,"nrm",quad[1]); + + auto pscale = verts("pscale",quad[0]); + auto kpscale = kverts("pscale",quad[1]); + + T minv = verts("minv",quad[0]); + // T kminv = kverts("minv",quad[1]); + + vec3 dp = {}; + auto thickness = pscale + kpscale; + thickness *= (float)1.01; + CONSTRAINT::solve_PlaneConstraint(p,minv,kp,knrm,thickness,s,dt,lambda,dp); + verts.tuple(dim_c<3>,ptag,quad[0]) = p + dp; + } + + cquads("lambda",coffset + gi) = lambda; + }); + + } + + // cudaPol(zs::range(verts.size())) + + set_output("constraints",constraints); + set_output("zsparticles",zsparticles); + set_output("target",target); + }; +}; + +ZENDEFNODE(XPBDSolve, {{{"zsparticles"},{"constraints"},{"target"},{"float","dt","0.5"}}, + {{"zsparticles"},{"constraints"},{"target"}}, + {{"string","ptag","X"}}, + {"PBD"}}); + +struct XPBDSolveSmooth : INode { + + virtual void apply() override { + using namespace zs; + using namespace PBD_CONSTRAINT; + + using vec3 = zs::vec; + using vec2i = zs::vec; + using vec3i = zs::vec; + using vec4i = zs::vec; + using mat4 = zs::vec; + + constexpr auto space = execspace_e::cuda; + auto cudaPol = cuda_exec(); + constexpr auto exec_tag = wrapv{}; + + auto zsparticles = get_input("zsparticles"); + + auto all_constraints = RETRIEVE_OBJECT_PTRS(ZenoParticles, "all_constraints"); + auto ptag = get_param("ptag"); + auto w = get_input2("relaxation_strength"); + + auto& verts = zsparticles->getParticles(); + + zs::Vector dp_buffer{verts.get_allocator(),verts.size() * 3}; + cudaPol(zs::range(dp_buffer),[]ZS_LAMBDA(auto& v) {v = 0;}); + zs::Vector dp_count{verts.get_allocator(),verts.size()}; + cudaPol(zs::range(dp_count),[]ZS_LAMBDA(auto& c) {c = 0;}); + + for(auto &&constraints : all_constraints) { + const auto& cquads = constraints->getQuadraturePoints(); + auto category = constraints->readMeta(CONSTRAINT_KEY,wrapt{}); + + cudaPol(zs::range(cquads.size()),[ + verts = proxy({},verts), + category, + // dt, + // w, + exec_tag, + dp_buffer = proxy(dp_buffer), + dp_count = proxy(dp_count), + ptag = zs::SmallString(ptag), + cquads = proxy({},cquads)] ZS_LAMBDA(int ci) mutable { + float s = cquads("stiffness",ci); + float lambda = cquads("lambda",ci); + + if(category == category_c::dihedral_bending_constraint) { + auto quad = cquads.pack(dim_c<4>,"inds",ci,int_c); + vec3 p[4] = {}; + float minv[4] = {}; + for(int i = 0;i != 4;++i) { + p[i] = verts.pack(dim_c<3>,ptag,quad[i]); + minv[i] = verts("minv",quad[i]); + } + + auto ra = cquads("ra",ci); + vec3 dp[4] = {}; + if(!CONSTRAINT::solve_DihedralConstraint( + p[0],minv[0], + p[1],minv[1], + p[2],minv[2], + p[3],minv[3], + ra, + s, + dp[0],dp[1],dp[2],dp[3])) + return; + for(int i = 0;i != 4;++i) + for(int j = 0;j != 3;++j) + atomic_add(exec_tag,&dp_buffer[quad[i] * 3 + j],dp[i][j]); + for(int i = 0;i != 4;++i) + atomic_add(exec_tag,&dp_count[quad[i]],(int)1); + } + + if(category == category_c::edge_length_constraint) { + auto edge = cquads.pack(dim_c<2>,"inds",ci,int_c); + vec3 p0{},p1{}; + p0 = verts.pack(dim_c<3>,ptag,edge[0]); + p1 = verts.pack(dim_c<3>,ptag,edge[1]); + float minv0 = verts("minv",edge[0]); + float minv1 = verts("minv",edge[1]); + float r = cquads("r",ci); + + vec3 dp0{},dp1{}; + if(!CONSTRAINT::solve_DistanceConstraint( + p0,minv0, + p1,minv1, + r, + (float)1, + dp0,dp1)) { + + for(int i = 0;i != 3;++i) + atomic_add(exec_tag,&dp_buffer[edge[0] * 3 + i],dp0[i]); + for(int i = 0;i != 3;++i) + atomic_add(exec_tag,&dp_buffer[edge[1] * 3 + i],dp1[i]); + + atomic_add(exec_tag,&dp_count[edge[0]],(int)1); + atomic_add(exec_tag,&dp_count[edge[1]],(int)1); + } + } + // if(category == category_c::isometric_bending_constraint) { + // return; + // auto quad = cquads.pack(dim_c<4>,"inds",ci,int_c); + // vec3 p[4] = {}; + // float minv[4] = {}; + // for(int i = 0;i != 4;++i) { + // p[i] = verts.pack(dim_c<3>,ptag,quad[i]); + // minv[i] = verts("minv",quad[i]); + // } + + // auto Q = cquads.pack(dim_c<4,4>,"Q",ci); + + // vec3 dp[4] = {}; + // float lambda = 0; + // CONSTRAINT::solve_IsometricBendingConstraint( + // p[0],minv[0], + // p[1],minv[1], + // p[2],minv[2], + // p[3],minv[3], + // Q, + // (float)1, + // dp[0], + // dp[1], + // dp[2], + // dp[3]); + + // auto has_nan = false; + // for(int i = 0;i != 4;++i) + // if(zs::isnan(dp[i].norm())) + // has_nan = true; + // if(has_nan) { + // printf("nan dp detected : %f %f %f %f %f %f %f %f\n", + // (float)p[0].norm(), + // (float)p[1].norm(), + // (float)p[2].norm(), + // (float)p[3].norm(), + // (float)dp[0].norm(), + // (float)dp[1].norm(), + // (float)dp[2].norm(), + // (float)dp[3].norm()); + // return; + // } + // for(int i = 0;i != 4;++i) + // for(int j = 0;j != 3;++j) + // atomic_add(exec_tag,&dp_buffer[quad[i] * 3 + j],dp[i][j]); + // for(int i = 0;i != 4;++i) + // atomic_add(exec_tag,&dp_count[quad[i]],(int)1); + // } + }); + } + + cudaPol(zs::range(verts.size()),[ + verts = proxy({},verts), + ptag = zs::SmallString(ptag),w, + dp_count = proxy(dp_count), + dp_buffer = proxy(dp_buffer)] ZS_LAMBDA(int vi) mutable { + if(dp_count[vi] > 0) { + auto dp = w * vec3{dp_buffer[vi * 3 + 0],dp_buffer[vi * 3 + 1],dp_buffer[vi * 3 + 2]}; + verts.tuple(dim_c<3>,ptag,vi) = verts.pack(dim_c<3>,ptag,vi) + dp / (T)dp_count[vi]; + } + }); + + // set_output("all_constraints",all_constraints); + set_output("zsparticles",zsparticles); + }; +}; + +ZENDEFNODE(XPBDSolveSmooth, {{{"zsparticles"},{"all_constraints"},{"float","relaxation_strength","1"}}, + {{"zsparticles"}}, + {{"string","ptag","x"}}, + {"PBD"}}); + + + + + +}; diff --git a/projects/CuLagrange/pbd/KinematicCollision.cu b/projects/CuLagrange/pbd/KinematicCollision.cu new file mode 100644 index 0000000000..475386644c --- /dev/null +++ b/projects/CuLagrange/pbd/KinematicCollision.cu @@ -0,0 +1,122 @@ +#include "Structures.hpp" +#include "zensim/Logger.hpp" +#include "zensim/cuda/execution/ExecutionPolicy.cuh" +#include "zensim/omp/execution/ExecutionPolicy.hpp" +#include "zensim/io/MeshIO.hpp" +#include "zensim/math/bit/Bits.h" +#include "zensim/types/Property.h" +#include +#include +#include +#include +#include +#include + +#include "../geometry/kernel/tiled_vector_ops.hpp" +#include "../geometry/kernel/topology.hpp" +#include "../geometry/kernel/geo_math.hpp" + +namespace zeno { + + +struct SDFColliderProject : INode { + using T = float; + using vec3 = zs::vec; + + virtual void apply() override { + using namespace zs; + constexpr auto space = execspace_e::cuda; + auto cudaPol = cuda_exec(); + + auto zsparticles = get_input("zsparticles"); + + auto radius = get_input2("radius"); + auto center = get_input2("center"); + auto cv = get_input2("center_velocity"); + auto w = get_input2("angular_velocity"); + + // prex + auto xtag = get_input2("xtag"); + // x + auto ptag = get_input2("ptag"); + auto friction = get_input2("friction"); + + // auto do_stablize = get_input2("do_stablize"); + + auto& verts = zsparticles->getParticles(); + + cudaPol(zs::range(verts.size()),[ + verts = proxy({},verts), + xtag = zs::SmallString(xtag), + ptag = zs::SmallString(ptag), + friction, + radius, + center, + // do_stablize, + cv,w] ZS_LAMBDA(int vi) mutable { + if(verts("minv",vi) < (T)1e-6) + return; + + auto pred = verts.pack(dim_c<3>,ptag,vi); + auto pos = verts.pack(dim_c<3>,xtag,vi); + + auto center_vel = vec3::from_array(cv); + auto center_pos = vec3::from_array(center); + auto angular_velocity = vec3::from_array(w); + + auto disp = pred - center_pos; + auto dist = radius - disp.norm() + verts("pscale",vi); + + if(dist < 0) + return; + + auto nrm = disp.normalized(); + + auto dp = dist * nrm; + if(dp.norm() < (T)1e-6) + return; + + pred += dp; + + // if(do_stablize) { + // pos += dp; + // verts.tuple(dim_c<3>,xtag,vi) = pos; + // } + + auto collider_velocity_at_p = center_vel + angular_velocity.cross(pred - center_pos); + auto rel_vel = pred - pos - center_vel; + + auto tan_vel = rel_vel - nrm * rel_vel.dot(nrm); + auto tan_len = tan_vel.norm(); + auto max_tan_len = dp.norm() * friction; + + if(tan_len > (T)1e-6) { + auto alpha = (T)max_tan_len / (T)tan_len; + dp = -tan_vel * zs::min(alpha,(T)1.0); + pred += dp; + } + + // dp = dp * verts("m",vi) * verts("minv",vi); + + verts.tuple(dim_c<3>,ptag,vi) = pred; + }); + set_output("zsparticles",zsparticles); + } + +}; + +ZENDEFNODE(SDFColliderProject, {{{"zsparticles"}, + {"float","radius","1"}, + {"center"}, + {"center_velocity"}, + {"angular_velocity"}, + {"string","xtag","x"}, + {"string","ptag","x"}, + {"float","friction","0"} + // {"bool","do_stablize","0"} + }, + {{"zsparticles"}}, + {}, + {"PBD"}}); + +}; \ No newline at end of file diff --git a/projects/CuLagrange/pbd/PBD.cuh b/projects/CuLagrange/pbd/PBD.cuh deleted file mode 100644 index 6bbae36a99..0000000000 --- a/projects/CuLagrange/pbd/PBD.cuh +++ /dev/null @@ -1,117 +0,0 @@ -#pragma once -#include "Structures.hpp" -#include "zensim/container/Bvh.hpp" -#include "zensim/container/Bvs.hpp" -#include "zensim/container/HashTable.hpp" -#include "zensim/container/Vector.hpp" -#include "zensim/cuda/Cuda.h" -#include "zensim/cuda/execution/ExecutionPolicy.cuh" -#include "zensim/math/Vec.h" -#include -#include -#include - -namespace zeno { - -struct PBDSystem : IObject { - using T = float; - using Ti = zs::conditional_t, zs::i64, zs::i32>; - using dtiles_t = zs::TileVector; - using tiles_t = typename ZenoParticles::particles_t; - using vec3 = zs::vec; - using mat3 = zs::vec; - using ivec3 = zs::vec; - using ivec2 = zs::vec; - using bvh_t = zs::LBvh<3, int, T>; - using bv_t = zs::AABBBox<3, T>; - - struct PrimitiveHandle { - PrimitiveHandle(ZenoParticles &zsprim, std::size_t &vOffset, std::size_t &sfOffset, std::size_t &seOffset, - std::size_t &svOffset, zs::wrapv<4>); - - void initGeo(); - - auto getModelLameParams() const { - T mu, lam; - zs::match([&](const auto &model) { - mu = model.mu; - lam = model.lam; - })(models.getElasticModel()); - return zs::make_tuple(mu, lam); - } - - decltype(auto) getVerts() const { - return *vertsPtr; - } - decltype(auto) getEles() const { - return *elesPtr; - } - decltype(auto) getEdges() const { - return *edgesPtr; - } - decltype(auto) getSurfTris() const { - return *surfTrisPtr; - } - decltype(auto) getSurfEdges() const { - return *surfEdgesPtr; - } - decltype(auto) getSurfVerts() const { - return *surfVertsPtr; - } - bool isBoundary() const noexcept { - return zsprimPtr->asBoundary; - } - - std::shared_ptr zsprimPtr{}; // nullptr if it is an auxiliary object - const ZenoConstitutiveModel ⊧ - std::shared_ptr vertsPtr; - std::shared_ptr elesPtr; - std::shared_ptr edgesPtr; - std::shared_ptr surfTrisPtr; - std::shared_ptr surfEdgesPtr; - std::shared_ptr surfVertsPtr; - // typename ZenoParticles::dtiles_t etemp; - // typename ZenoParticles::dtiles_t svtemp; - const std::size_t vOffset, sfOffset, seOffset, svOffset; - ZenoParticles::category_e category; - }; - - void initialize(zs::CudaExecutionPolicy &pol); - PBDSystem(std::vector zsprims, vec3 extForce, T dt, int numSolveIters, T ec, T vc); - - void reinitialize(zs::CudaExecutionPolicy &pol, T framedt); - void writebackPositionsAndVelocities(zs::CudaExecutionPolicy &pol); - - /// pipeline - void preSolve(zs::CudaExecutionPolicy &pol); - void solveEdge(zs::CudaExecutionPolicy &pol); - void solveVolume(zs::CudaExecutionPolicy &pol); - void postSolve(zs::CudaExecutionPolicy &pol); - - // sim params - vec3 extForce; - int solveIterCap = 50; - T edgeCompliance = 0.001, volumeCompliance = 0.001; - - // - std::vector prims; - std::size_t coOffset, numDofs; - std::size_t sfOffset, seOffset, svOffset; - - dtiles_t vtemp; - - zs::Vector temp; - - // boundary contacts - // auxiliary data (spatial acceleration) - tiles_t stInds, seInds, svInds; - // using bvs_t = zs::LBvs<3, int, T>; - bvh_t stBvh, seBvh; // for simulated objects - // bvs_t stBvs, seBvs; // STQ - // bvh_t bouStBvh, bouSeBvh; // for collision objects - // bvs_t bouStBvs, bouSeBvs; // STQ - T dt, framedt; -}; -// config compliance, num solve iters, edge/volume extforce, dt - -} // namespace zeno \ No newline at end of file diff --git a/projects/CuLagrange/pbd/PBDInit.cu b/projects/CuLagrange/pbd/PBDInit.cu deleted file mode 100644 index 4f47fbb3c3..0000000000 --- a/projects/CuLagrange/pbd/PBDInit.cu +++ /dev/null @@ -1,227 +0,0 @@ -#include "PBD.cuh" -#include "Utils.hpp" - -namespace zeno { - -void PBDSystem::PrimitiveHandle::initGeo() { - // init rest volumes & edge lengths - auto cudaPol = zs::cuda_exec(); - using namespace zs; - constexpr auto space = zs::execspace_e::cuda; - elesPtr->append_channels(cudaPol, {{"rv", 1}}); - cudaPol(zs::Collapse{elesPtr->size()}, - [eles = proxy({}, *elesPtr), verts = proxy({}, *vertsPtr)] ZS_LAMBDA(int ei) mutable { - auto quad = eles.template pack<4>("inds", ei).template reinterpret_bits(); - vec3 xs[4]; - for (int d = 0; d != 4; ++d) - xs[d] = verts.template pack<3>("x", quad[d]); - vec3 ds[3] = {xs[1] - xs[0], xs[2] - xs[0], xs[3] - xs[0]}; -#if 0 - mat3 D{}; - for (int d = 0; d != 3; ++d) - for (int i = 0; i != 3; ++i) - D(d, i) = ds[i][d]; - T vol = zs::abs(zs::determinant(D)) / 6; -#else - T vol = zs::abs((ds[0]).cross(ds[1]).dot(ds[2])) / 6; -#endif - eles("rv", ei) = vol; - }); - edgesPtr->append_channels(cudaPol, {{"rl", 1}}); - cudaPol(zs::Collapse{edgesPtr->size()}, - [ses = proxy({}, *edgesPtr), verts = proxy({}, *vertsPtr)] ZS_LAMBDA(int sei) mutable { - auto line = ses.template pack<2>("inds", sei).template reinterpret_bits(); - vec3 xs[2]; - for (int d = 0; d != 2; ++d) - xs[d] = verts.template pack<3>("x", line[d]); - ses("rl", sei) = (xs[1] - xs[0]).length(); - }); -} - -PBDSystem::PrimitiveHandle::PrimitiveHandle(ZenoParticles &zsprim, std::size_t &vOffset, std::size_t &sfOffset, - std::size_t &seOffset, std::size_t &svOffset, zs::wrapv<4>) - : zsprimPtr{&zsprim, [](void *) {}}, models{zsprim.getModel()}, vertsPtr{&zsprim.getParticles(), [](void *) {}}, - elesPtr{&zsprim.getQuadraturePoints(), [](void *) {}}, edgesPtr{&zsprim[ZenoParticles::s_edgeTag], [](void *) {}}, - surfTrisPtr{&zsprim[ZenoParticles::s_surfTriTag], [](void *) {}}, - surfEdgesPtr{&zsprim[ZenoParticles::s_surfEdgeTag], [](void *) {}}, - surfVertsPtr{&zsprim[ZenoParticles::s_surfVertTag], [](void *) {}}, vOffset{vOffset}, sfOffset{sfOffset}, - seOffset{seOffset}, svOffset{svOffset}, category{zsprim.category} { - if (category != ZenoParticles::tet) - throw std::runtime_error("dimension of 4 but is not tetrahedra"); - initGeo(); - vOffset += getVerts().size(); - sfOffset += getSurfTris().size(); - seOffset += getSurfEdges().size(); - svOffset += getSurfVerts().size(); -} - -void PBDSystem::initialize(zs::CudaExecutionPolicy &pol) { - using namespace zs; - constexpr auto space = execspace_e::cuda; - stInds = tiles_t{vtemp.get_allocator(), {{"inds", 3}}, sfOffset}; - seInds = tiles_t{vtemp.get_allocator(), {{"inds", 2}}, seOffset}; - svInds = tiles_t{vtemp.get_allocator(), {{"inds", 1}}, svOffset}; - for (auto &primHandle : prims) { - auto &verts = primHandle.getVerts(); - // record surface (tri) indices - if (primHandle.category != ZenoParticles::category_e::curve) { - auto &tris = primHandle.getSurfTris(); - pol(Collapse(tris.size()), - [stInds = proxy({}, stInds), tris = proxy({}, tris), voffset = primHandle.vOffset, - sfoffset = primHandle.sfOffset] __device__(int i) mutable { - stInds.template tuple<3>("inds", sfoffset + i) = - (tris.template pack<3>("inds", i).template reinterpret_bits() + (int)voffset) - .template reinterpret_bits(); - }); - } - auto &edges = primHandle.getSurfEdges(); - pol(Collapse(edges.size()), - [seInds = proxy({}, seInds), edges = proxy({}, edges), voffset = primHandle.vOffset, - seoffset = primHandle.seOffset] __device__(int i) mutable { - seInds.template tuple<2>("inds", seoffset + i) = - (edges.template pack<2>("inds", i).template reinterpret_bits() + (int)voffset) - .template reinterpret_bits(); - }); - auto &points = primHandle.getSurfVerts(); - pol(Collapse(points.size()), - [svInds = proxy({}, svInds), points = proxy({}, points), voffset = primHandle.vOffset, - svoffset = primHandle.svOffset] __device__(int i) mutable { - svInds("inds", svoffset + i) = - reinterpret_bits(reinterpret_bits(points("inds", i)) + (int)voffset); - }); - } - // init mass - pol(Collapse(numDofs), [vtemp = proxy({}, vtemp)] __device__(int i) mutable { vtemp("m", i) = 0; }); - for (auto &primHandle : prims) { - auto density = primHandle.models.density; - auto &eles = primHandle.getEles(); - pol(Collapse(eles.size()), [vtemp = proxy({}, vtemp), eles = proxy({}, eles), - vOffset = primHandle.vOffset, density] __device__(int ei) mutable { - auto m = eles("rv", ei) * density; - auto inds = eles.template pack<4>("inds", ei).template reinterpret_bits() + vOffset; - for (int d = 0; d != 4; ++d) - atomic_add(exec_cuda, &vtemp("m", inds[d]), m / 4); - }); - } - reinitialize(pol, dt); -} - -void PBDSystem::reinitialize(zs::CudaExecutionPolicy &pol, T framedt) { - using namespace zs; - constexpr auto space = execspace_e::cuda; - this->framedt = framedt; - this->dt = framedt / solveIterCap; // substep dt - for (auto &primHandle : prims) { - auto &verts = primHandle.getVerts(); - // initialize BC info - // predict pos, initialize augmented lagrangian, constrain weights - pol(Collapse(verts.size()), [vtemp = proxy({}, vtemp), verts = proxy({}, verts), - voffset = primHandle.vOffset, dt = dt] __device__(int i) mutable { - auto x = verts.pack<3>("x", i); - auto v = verts.pack<3>("v", i); - vtemp.tuple<3>("x", voffset + i) = x; - vtemp.tuple<3>("xpre", voffset + i) = x; - vtemp.tuple<3>("v", voffset + i) = v; - }); - } -} - -PBDSystem::PBDSystem(std::vector zsprims, vec3 extForce, T dt, int numSolveIters, T ec, T vc) - : extForce{extForce}, solveIterCap{numSolveIters}, edgeCompliance{ec}, volumeCompliance{vc}, prims{}, coOffset{0}, - numDofs{0}, sfOffset{0}, seOffset{0}, svOffset{0}, vtemp{}, temp{}, stInds{}, seInds{}, svInds{}, dt{dt} { - for (auto primPtr : zsprims) { - if (primPtr->category == ZenoParticles::category_e::tet) { - prims.emplace_back(*primPtr, coOffset, sfOffset, seOffset, svOffset, zs::wrapv<4>{}); - } - } - zeno::log_info("num total obj : {}, {}, {}, {}\n", coOffset, svOffset, seOffset, - sfOffset); - numDofs = coOffset; // if there are boundaries, then updated - vtemp = dtiles_t{zsprims[0]->getParticles().get_allocator(), {{"m", 1}, {"x", 3}, {"xpre", 3}, {"v", 3}}, numDofs}; - - auto cudaPol = zs::cuda_exec(); - initialize(cudaPol); -} - -struct ExtractTetEdges : INode { - void apply() override { - using namespace zs; - - auto zstets = RETRIEVE_OBJECT_PTRS(ZenoParticles, "ZSParticles"); - for (auto tet : zstets) { - using ivec2 = zs::vec; - auto comp_v2 = [](const ivec2 &x, const ivec2 &y) { - return x[0] < y[0] ? 1 : (x[0] == y[0] && x[1] < y[1] ? 1 : 0); - }; - std::set sedges(comp_v2); - std::vector lines(0); - auto ist2 = [&sedges, &lines](int i, int j) { - if (sedges.find(ivec2{i, j}) == sedges.end() && sedges.find(ivec2{j, i}) == sedges.end()) { - sedges.insert(ivec2{i, j}); - lines.push_back(ivec2{i, j}); - } - }; - const auto &elements = tet->getQuadraturePoints().clone({memsrc_e::host, -1}); - constexpr auto space = execspace_e::host; - auto eles = proxy({}, elements); - for (int ei = 0; ei != eles.size(); ++ei) { - auto inds = eles.template pack<4>("inds", ei).template reinterpret_bits(); - ist2(inds[0], inds[1]); - ist2(inds[0], inds[2]); - ist2(inds[0], inds[3]); - ist2(inds[1], inds[2]); - ist2(inds[1], inds[3]); - ist2(inds[2], inds[3]); - } - auto &edges = (*tet)[ZenoParticles::s_edgeTag]; - edges = typename ZenoParticles::particles_t{{{"inds", 2}}, lines.size(), memsrc_e::host, -1}; - auto ev = proxy({}, edges); - for (int i = 0; i != lines.size(); ++i) { - ev("inds", 0, i) = reinterpret_bits((int)lines[i][0]); - ev("inds", 1, i) = reinterpret_bits((int)lines[i][1]); - } - edges = edges.clone(tet->getParticles().get_allocator()); - } - - set_output("ZSParticles", get_input("ZSParticles")); - } -}; - -ZENDEFNODE(ExtractTetEdges, {{ - "ZSParticles", - }, - {"ZSParticles"}, - {}, - {"PBD"}}); - -struct MakePBDSystem : INode { - void apply() override { - using namespace zs; - auto zstets = RETRIEVE_OBJECT_PTRS(ZenoParticles, "ZSParticles"); - /// solver parameters - auto input_cap = get_input2("iter_cap"); - auto dt = get_input2("dt"); - auto ec = get_input2("edge_compliance"); - auto vc = get_input2("edge_compliance"); - auto extForce = get_input("ext_force")->get(); - - auto A = std::make_shared(zstets, zs::vec{extForce[0], extForce[1], extForce[2]}, dt, - input_cap, ec, vc); - - set_output("ZSPBDSystem", A); - } -}; - -ZENDEFNODE(MakePBDSystem, {{ - "ZSParticles", - {"float", "dt", "0.01"}, - {"vec3f", "ext_force", "0,-9,0"}, - {"int", "iter_cap", "100"}, - {"float", "edge_compliance", "0.001"}, - {"float", "volume_compliance", "0.001"}, - }, - {"ZSPBDSystem"}, - {}, - {"PBD"}}); - -} // namespace zeno \ No newline at end of file diff --git a/projects/CuLagrange/pbd/PBDPipeline.cu b/projects/CuLagrange/pbd/PBDPipeline.cu deleted file mode 100644 index 32e347b247..0000000000 --- a/projects/CuLagrange/pbd/PBDPipeline.cu +++ /dev/null @@ -1,152 +0,0 @@ -#include "PBD.cuh" -#include "zensim/execution/ExecutionPolicy.hpp" - -namespace zeno { - -void PBDSystem::preSolve(zs::CudaExecutionPolicy &pol) { - using namespace zs; - constexpr auto space = execspace_e::cuda; - pol(range(numDofs), [vtemp = proxy({}, vtemp), extForce = extForce, dt = dt] ZS_LAMBDA(int i) mutable { - auto x = vtemp.template pack<3>("x", i); - auto v = vtemp.template pack<3>("v", i); - auto xpre = x; - v += extForce * dt; //extForce here is actually accel - x += v * dt; - // project - if (x[1] < 0) { - x = xpre; - x[1] = 0; - } - vtemp.template tuple<3>("xpre", i) = xpre; - vtemp.template tuple<3>("x", i) = x; - vtemp.template tuple<3>("v", i) = v; - }); -} - -void PBDSystem::solveEdge(zs::CudaExecutionPolicy &pol) { - using namespace zs; - constexpr auto space = execspace_e::cuda; - T alpha = edgeCompliance / dt / dt; - zeno::vec3f grads{0, 0, 0}; - for (auto &&prim : prims) { - auto &edges = prim.getEdges(); - pol(range(edges.size()), [vtemp = proxy({}, vtemp), edges = proxy({}, edges), - vOffset = prim.vOffset, alpha] ZS_LAMBDA(int ei) mutable { - auto id = edges.template pack<2>("inds", ei).template reinterpret_bits() + vOffset; - T ms[2]; - ms[0] = 1 / vtemp("m", id[0]); - ms[1] = 1 / vtemp("m", id[1]); - vec3 grads; - auto x0 = vtemp.template pack<3>("x", id[0]); - auto x1 = vtemp.template pack<3>("x", id[1]); - grads = x0 - x1; - auto len = grads.length(); - grads /= len; - T C = len - edges("rl", ei); - T w = ms[0] + ms[1]; - T s = -C / (w + alpha); - - for (int d = 0; d != 3; ++d) { - atomic_add(exec_cuda, &vtemp("x", d, id[0]), grads[d] * s * ms[0]); - atomic_add(exec_cuda, &vtemp("x", d, id[1]), grads[d] * -s * ms[1]); - } - }); - } -} -void PBDSystem::solveVolume(zs::CudaExecutionPolicy &pol) { - using namespace zs; - constexpr auto space = execspace_e::cuda; - float alphaVol = volumeCompliance / dt / dt; - - for (auto &&prim : prims) { - auto &eles = prim.getEles(); - pol(range(eles.size()), [vtemp = proxy({}, vtemp), eles = proxy({}, eles), vOffset = prim.vOffset, - alphaVol] ZS_LAMBDA(int ei) mutable { - auto id = eles.template pack<4>("inds", ei).template reinterpret_bits() + vOffset; - vec3 gradsVol[4]; - T ms[4]; - auto x0 = vtemp.template pack<3>("x", id[0]); - auto x1 = vtemp.template pack<3>("x", id[1]); - auto x2 = vtemp.template pack<3>("x", id[2]); - auto x3 = vtemp.template pack<3>("x", id[3]); - ms[0] = 1 / vtemp("m", id[0]); - ms[1] = 1 / vtemp("m", id[1]); - ms[2] = 1 / vtemp("m", id[2]); - ms[3] = 1 / vtemp("m", id[3]); - - // ref: https://github.com/InteractiveComputerGraphics/PositionBasedDynamics - // XPBD.cpp:solve_VolumeConstraint - gradsVol[0] = (x1 - x2).cross(x3 - x2); - gradsVol[1] = (x2 - x0).cross(x3 - x0); - gradsVol[2] = (x0 - x1).cross(x3 - x1); - gradsVol[3] = (x1 - x0).cross(x2 - x0); - - T w = 0; - for (int j = 0; j != 4; ++j) - w += gradsVol[j].l2NormSqr() * ms[j]; - - T vol = zs::abs((x1 - x0).cross(x2 - x0).dot(x3 - x0)) / 6; - T C = (vol - eles("rv", ei)) * 6; - T s = -C / (w + alphaVol); - - for (int j = 0; j != 4; ++j) - for (int d = 0; d != 3; ++d) - atomic_add(exec_cuda, &vtemp("x", d, id[j]), gradsVol[j][d] * s * ms[j]); - }); - } -} - -void PBDSystem::postSolve(zs::CudaExecutionPolicy &pol) { - using namespace zs; - constexpr auto space = execspace_e::cuda; - pol(range(numDofs), [vtemp = proxy({}, vtemp), dt = dt] ZS_LAMBDA(int i) mutable { - auto x = vtemp.template pack<3>("x", i); - auto xpre = vtemp.template pack<3>("xpre", i); - auto v = (x - xpre) / dt; - vtemp.template tuple<3>("v", i) = v; - }); -} - -void PBDSystem::writebackPositionsAndVelocities(zs::CudaExecutionPolicy &pol) { - using namespace zs; - constexpr auto space = execspace_e::cuda; - for (auto &primHandle : prims) { - auto &verts = primHandle.getVerts(); - // update velocity and positions - pol(zs::range(verts.size()), [vtemp = proxy({}, vtemp), verts = proxy({}, verts), dt = dt, - vOffset = primHandle.vOffset] __device__(int vi) mutable { - verts.tuple<3>("x", vi) = vtemp.pack<3>("x", vOffset + vi); - verts.tuple<3>("v", vi) = vtemp.pack<3>("v", vOffset + vi); - }); - } -} - -struct StepPBDSystem : INode { - void apply() override { - using namespace zs; - auto A = get_input("ZSPBDSystem"); - auto dt = get_input2("dt"); - - auto cudaPol = cuda_exec(); - A->reinitialize(cudaPol, dt); - for (int steps = 0; steps != A->solveIterCap; ++steps) { - A->preSolve(cudaPol); - A->solveEdge(cudaPol); - A->solveVolume(cudaPol); - A->postSolve(cudaPol); - } - A->writebackPositionsAndVelocities(cudaPol); - - set_output("ZSPBDSystem", A); - } -}; - -ZENDEFNODE(StepPBDSystem, {{ - "ZSPBDSystem", - {"float", "dt", "0.01"}, - }, - {"ZSPBDSystem"}, - {}, - {"PBD"}}); - -} // namespace zeno \ No newline at end of file diff --git a/projects/CuLagrange/pbd/SelfCollision.cu b/projects/CuLagrange/pbd/SelfCollision.cu new file mode 100644 index 0000000000..74cec669b7 --- /dev/null +++ b/projects/CuLagrange/pbd/SelfCollision.cu @@ -0,0 +1,831 @@ +#include "Structures.hpp" +#include "zensim/Logger.hpp" +#include "zensim/cuda/execution/ExecutionPolicy.cuh" +#include "zensim/omp/execution/ExecutionPolicy.hpp" +#include "zensim/io/MeshIO.hpp" +#include "zensim/math/bit/Bits.h" +#include "zensim/types/Property.h" +#include +#include +#include +#include +#include +#include + +// #include "constraint_function_kernel/constraint.cuh" +#include "../geometry/kernel/tiled_vector_ops.hpp" +#include "../geometry/kernel/topology.hpp" +#include "../geometry/kernel/geo_math.hpp" +#include "../fem/collision_energy/evaluate_collision.hpp" +// #include "constraint_function_kernel/constraint_types.hpp" + +namespace zeno { + +struct DetangleImminentCollision : INode { + using T = float; + using vec3 = zs::vec; + using dtiles_t = zs::TileVector; + + virtual void apply() override { + using namespace zs; + constexpr auto space = execspace_e::cuda; + auto cudaPol = cuda_exec(); + using bv_t = typename ZenoLinearBvh::lbvh_t::Box; + // constexpr auto exec_tag = wrapv{}; + constexpr auto eps = (T)1e-7; + + auto zsparticles = get_input("zsparticles"); + auto current_x_tag = get_input2("current_x_tag"); + auto pre_x_tag = get_input2("previous_x_tag"); + auto repel_strength = get_input2("repeling_strength"); + auto imminent_collision_thickness = get_input2("immc_thickness"); + // apply impulse for imminent collision for previous configuration + auto& verts = zsparticles->getParticles(); + const auto& tris = zsparticles->getQuadraturePoints(); + const auto& halfedges = (*zsparticles)[ZenoParticles::s_surfHalfEdgeTag]; + const auto &edges = (*zsparticles)[ZenoParticles::s_surfEdgeTag]; + + if(!verts.hasProperty("imminent_fail")) + verts.append_channels(cudaPol,{{"imminent_fail",1}}); + cudaPol(zs::range(verts.size()),[ + verts = proxy({},verts)] ZS_LAMBDA(int vi) mutable {verts("imminent_fail",vi) = (T)0;}); + + dtiles_t vtemp{verts.get_allocator(),{ + {"x",3}, + {"v",3}, + {"minv",1} + },verts.size()}; + TILEVEC_OPS::copy(cudaPol,verts,pre_x_tag,vtemp,"x"); + TILEVEC_OPS::copy(cudaPol,verts,"minv",vtemp,"minv"); + cudaPol(zs::range(verts.size()),[ + verts = proxy({},verts), + vtemp = proxy({},vtemp), + current_x_tag = zs::SmallString(current_x_tag)] ZS_LAMBDA(int vi) mutable { + vtemp.tuple(dim_c<3>,"v",vi) = verts.pack(dim_c<3>,current_x_tag,vi) - vtemp.pack(dim_c<3>,"x",vi); + }); + // TILEVEC_OPS::copy(cudaPol,verts,current_x_tag,vtemp,"v"); + // TILEVEC_OPS::add(cudaPol,vtemp,"v",1,"x",-1,"v"); + dtiles_t imminent_collision_buffer(verts.get_allocator(), + { + {"inds",4}, + {"bary",4}, + {"impulse",3}, + {"collision_normal",3} + },(size_t)0); + + auto imminent_restitution_rate = get_input2("imm_restitution"); + auto imminent_relaxation_rate = get_input2("imm_relaxation"); + + auto nm_iters = get_input2("nm_imminent_iters"); + + auto do_pt_detection = get_input2("use_PT"); + auto do_ee_detection = get_input2("use_EE"); + + zs::Vector nm_imminent_collision{verts.get_allocator(),(size_t)1}; + + std::cout << "do imminent detangle" << std::endl; + + auto vn_threshold = 5e-3; + + for(int it = 0;it != nm_iters;++it) { + + cudaPol(zs::range(verts.size()),[ + verts = proxy({},verts)] ZS_LAMBDA(int vi) mutable {verts("imminent_fail",vi) = (T)0;}); + + // we use collision cell as the collision volume, PT collision is enough prevent penertation? + if(do_pt_detection) { + COLLISION_UTILS::calc_imminent_self_PT_collision_impulse(cudaPol, + vtemp,"x","v", + tris, + halfedges, + imminent_collision_thickness, + 0, + imminent_collision_buffer); + // std::cout << "nm_imminent_PT_collision : " << imminent_collision_buffer.size() << std::endl; + } + + if(do_ee_detection) { + COLLISION_UTILS::calc_imminent_self_EE_collision_impulse(cudaPol, + vtemp,"x","v", + edges, + imminent_collision_thickness, + imminent_collision_buffer.size(), + imminent_collision_buffer); + // std::cout << "nm_imminent_EE_collision : " << imminent_collision_buffer.size() << std::endl; + } + // resolve imminent PT collision + + // impulse_norm = TILEVEC_OPS::dot<3>(cudaPol,imminent_collision_buffer,"impulse","impulse"); + // std::cout << "EE_PT_impulse_norm : " << impulse_norm << std::endl; + + COLLISION_UTILS::apply_impulse(cudaPol, + vtemp,"v", + imminent_restitution_rate, + imminent_relaxation_rate, + imminent_collision_buffer); + + + auto add_repulsion_force = get_input2("add_repulsion_force"); + // add an impulse to repel the pair further + + nm_imminent_collision.setVal(0); + // if(add_repulsion_force) { + // std::cout << "add imminent replering force" << std::endl; + auto max_repel_distance = get_input2("max_repel_distance"); + + cudaPol(zs::range(imminent_collision_buffer.size()),[ + imminent_collision_buffer = proxy({},imminent_collision_buffer)] ZS_LAMBDA(int ci) mutable { + imminent_collision_buffer.tuple(dim_c<3>,"impulse",ci) = vec3::zeros(); + }); + + cudaPol(zs::range(imminent_collision_buffer.size()),[ + verts = proxy({},verts), + vtemp = proxy({},vtemp), + eps = eps, + exec_tag = wrapv{}, + k = repel_strength, + vn_threshold = vn_threshold, + max_repel_distance = max_repel_distance, + thickness = imminent_collision_thickness, + nm_imminent_collision = proxy(nm_imminent_collision), + imminent_collision_buffer = proxy({},imminent_collision_buffer)] ZS_LAMBDA(auto id) mutable { + auto inds = imminent_collision_buffer.pack(dim_c<4>,"inds",id,int_c); + auto bary = imminent_collision_buffer.pack(dim_c<4>,"bary",id); + + vec3 ps[4] = {}; + vec3 vs[4] = {}; + auto vr = vec3::zeros(); + auto pr = vec3::zeros(); + for(int i = 0;i != 4;++i) { + ps[i] = vtemp.pack(dim_c<3>,"x",inds[i]); + vs[i] = vtemp.pack(dim_c<3>,"v",inds[i]); + pr += bary[i] * ps[i]; + vr += bary[i] * vs[i]; + } + + auto dist = pr.norm(); + vec3 collision_normal = imminent_collision_buffer.pack(dim_c<3>,"collision_normal",id); + + if(dist > thickness) + return; + + auto d = thickness - dist; + auto vn = vr.dot(collision_normal); + if(vn < -vn_threshold) { + atomic_add(exec_tag,&nm_imminent_collision[0],1); + for(int i = 0;i != 4;++i) + verts("imminent_fail",inds[i]) = (T)1.0; + } + if(vn > (T)max_repel_distance * d || d < 0) { + // if with current velocity, the collided particles can be repeled by more than 1% of collision depth, no extra repulsion is needed + return; + } else { + // make sure the collided particles is seperated by 1% of collision depth + // assume the particles has the same velocity + auto I = k * d; + auto I_max = (max_repel_distance * d - vn); + I = I_max < I ? I_max : I; + auto impulse = (T)I * collision_normal; + + imminent_collision_buffer.tuple(dim_c<3>,"impulse",id) = impulse; + } + }); + std::cout << "nm_imminent_collision : " << nm_imminent_collision.getVal(0) << std::endl; + if(nm_imminent_collision.getVal(0) == 0) + break; + + + // auto impulse_norm = TILEVEC_OPS::dot<3>(cudaPol,imminent_collision_buffer,"impulse","impulse"); + // std::cout << "REPEL_impulse_norm : " << impulse_norm << std::endl; + + COLLISION_UTILS::apply_impulse(cudaPol, + vtemp,"v", + imminent_restitution_rate, + imminent_relaxation_rate, + imminent_collision_buffer); + // } + } + + std::cout << "finish imminent collision" << std::endl; + + cudaPol(zs::range(verts.size()),[ + verts = proxy({},verts), + vtemp = proxy({},vtemp), + current_x_tag = zs::SmallString(current_x_tag)] ZS_LAMBDA(int vi) mutable { + verts.tuple(dim_c<3>,current_x_tag,vi) = vtemp.pack(dim_c<3>,"x",vi) + vtemp.pack(dim_c<3>,"v",vi); + }); + + // std::cout << "finish apply imminent impulse" << std::endl; + + set_output("zsparticles",zsparticles); + } +}; + +ZENDEFNODE(DetangleImminentCollision, {{{"zsparticles"}, + {"string","current_x_tag","x"}, + {"string","previous_x_tag","px"}, + // {"string","pscaleTag","pscale"}, + {"float","repeling_strength","1.0"}, + {"float","immc_thickness","0.01"}, + {"int","nm_imminent_iters","1"}, + {"float","imm_restitution","0.1"}, + {"float","imm_relaxation","0.25"}, + {"float","max_repel_distance","0.1"}, + {"bool","add_repulsion_force","0"}, + {"bool","use_PT","1"}, + {"bool","use_EE","1"}, + }, + {{"zsparticles"}}, + {}, + {"PBD"}}); + + +struct VisualizeImminentCollision : INode { + using T = float; + using vec3 = zs::vec; + using dtiles_t = zs::TileVector; + + virtual void apply() override { + using namespace zs; + constexpr auto space = execspace_e::cuda; + auto cudaPol = cuda_exec(); + auto ompPol = omp_exec(); + constexpr auto omp_space = execspace_e::openmp; + + using bv_t = typename ZenoLinearBvh::lbvh_t::Box; + constexpr auto exec_tag = wrapv{}; + constexpr auto eps = (T)1e-7; + constexpr auto MAX_PT_COLLISION_PAIRS = 1000000; + + auto zsparticles = get_input("zsparticles"); + auto current_x_tag = get_input2("current_x_tag"); + auto pre_x_tag = get_input2("previous_x_tag"); + auto imminent_collision_thickness = get_input2("immc_thickness"); + + // apply impulse for imminent collision for previous configuration + auto& verts = zsparticles->getParticles(); + const auto& tris = zsparticles->getQuadraturePoints(); + const auto& edges = (*zsparticles)[ZenoParticles::s_surfEdgeTag]; + const auto& halfedges = (*zsparticles)[ZenoParticles::s_surfHalfEdgeTag]; + + // auto nm_imminent_iters = get_input2("nm_imminent_iters"); + dtiles_t imminent_PT_collision_buffer(verts.get_allocator(), + { + {"inds",4}, + {"bary",4}, + {"impulse",3}, + {"collision_normal",3} + },(size_t)0); + + dtiles_t imminent_EE_collision_buffer(verts.get_allocator(), + { + {"inds",4}, + {"bary",4}, + {"impulse",3}, + {"collision_normal",3} + },(size_t)0); + // zs::bht csPT{verts.get_allocator(),MAX_PT_COLLISION_PAIRS}; + // csPT.reset(cudaPol,true); + + dtiles_t vtemp(verts.get_allocator(),{ + {"x",3}, + {"v",3}, + {"minv",1} + },verts.size()); + TILEVEC_OPS::copy(cudaPol,verts,pre_x_tag,vtemp,"x"); + TILEVEC_OPS::copy(cudaPol,verts,"minv",vtemp,"minv"); + cudaPol(zs::range(verts.size()),[ + verts = proxy({},verts), + vtemp = proxy({},vtemp), + current_x_tag = zs::SmallString(current_x_tag)] ZS_LAMBDA(int vi) mutable { + vtemp.tuple(dim_c<3>,"v",vi) = verts.pack(dim_c<3>,current_x_tag,vi) - vtemp.pack(dim_c<3>,"x",vi); + }); + // we use collision cell as the collision volume, PT collision is enough prevent penertation? + COLLISION_UTILS::calc_imminent_self_PT_collision_impulse(cudaPol, + vtemp,"x","v", + tris, + halfedges, + imminent_collision_thickness, + 0, + imminent_PT_collision_buffer); + std::cout << "nm_PT_collision : " << imminent_PT_collision_buffer.size() << std::endl; + + COLLISION_UTILS::calc_imminent_self_EE_collision_impulse(cudaPol, + vtemp,"x","v", + edges, + imminent_collision_thickness, + 0, + imminent_EE_collision_buffer); + std::cout << "nm_EE_collision : " << imminent_EE_collision_buffer.size() << std::endl; + // resolve imminent PT collision + + dtiles_t imminent_PT_collision_vis(verts.get_allocator(),{ + {"collision_normal",3}, + {"pt",3}, + {"pp",3}},imminent_PT_collision_buffer.size()); + + cudaPol(zs::range(imminent_PT_collision_buffer.size()),[ + vtemp = proxy({},vtemp), + imminent_PT_collision_vis = proxy({},imminent_PT_collision_vis), + imminent_PT_collision_buffer = proxy({},imminent_PT_collision_buffer)] ZS_LAMBDA(auto ci) mutable { + auto inds = imminent_PT_collision_buffer.pack(dim_c<4>,"inds",ci,int_c); + auto bary = imminent_PT_collision_buffer.pack(dim_c<4>,"bary",ci); + + vec3 ps[4] = {}; + for(int i = 0;i != 4;++i) + ps[i] = vtemp.pack(dim_c<3>,"x",inds[i]); + + auto proj_t = vec3::zeros(); + auto pr = vec3::zeros(); + for(int i = 0;i != 4;++i) + pr += bary[i] * ps[i]; + + for(int i = 0;i != 3;++i) + proj_t -= bary[i] * ps[i]; + + auto collision_normal = pr.normalized(); + + imminent_PT_collision_vis.tuple(dim_c<3>,"collision_normal",ci) = collision_normal; + + imminent_PT_collision_vis.tuple(dim_c<3>,"pt",ci) = proj_t; + imminent_PT_collision_vis.tuple(dim_c<3>,"pp",ci) = vtemp.pack(dim_c<3>,"x",inds[3]); + }); + imminent_PT_collision_vis = imminent_PT_collision_vis.clone({zs::memsrc_e::host}); + + auto prim_PT = std::make_shared(); + auto& vis_verts_PT = prim_PT->verts; + auto& vis_lines_PT = prim_PT->lines; + vis_verts_PT.resize(imminent_PT_collision_buffer.size() * 2); + vis_lines_PT.resize(imminent_PT_collision_buffer.size()); + + auto nrm_prim_PT = std::make_shared(); + auto& nrm_verts_PT = nrm_prim_PT->verts; + auto& nrm_lines_PT = nrm_prim_PT->lines; + nrm_verts_PT.resize(imminent_PT_collision_buffer.size() * 2); + nrm_lines_PT.resize(imminent_PT_collision_buffer.size()); + + ompPol(zs::range(imminent_PT_collision_buffer.size()),[ + &vis_verts_PT,&vis_lines_PT, + &nrm_verts_PT,&nrm_lines_PT, + imminent_PT_collision_vis = proxy({},imminent_PT_collision_vis)] (int ci) mutable { + auto cnrm = imminent_PT_collision_vis.pack(dim_c<3>,"collision_normal",ci); + auto pt = imminent_PT_collision_vis.pack(dim_c<3>,"pt",ci); + auto pp = imminent_PT_collision_vis.pack(dim_c<3>,"pp",ci); + auto pn = pp + cnrm; + + vis_verts_PT[ci * 2 + 0] = pp.to_array(); + vis_verts_PT[ci * 2 + 1] = pt.to_array(); + vis_lines_PT[ci] = zeno::vec2i{ci * 2 + 0,ci * 2 + 1}; + + nrm_verts_PT[ci * 2 + 0] = pp.to_array(); + nrm_verts_PT[ci * 2 + 1] = pn.to_array(); + nrm_lines_PT[ci] = zeno::vec2i{ci * 2 + 0,ci * 2 + 1}; + }); + + set_output("prim_PT",std::move(prim_PT)); + set_output("cnrm_PT",std::move(nrm_prim_PT)); + + std::cout << "output PT VIS" << std::endl; + + + dtiles_t imminent_EE_collision_vis(verts.get_allocator(),{ + {"collision_normal",3}, + {"pt",3}, + {"pp",3}},imminent_EE_collision_buffer.size()); + + cudaPol(zs::range(imminent_EE_collision_buffer.size()),[ + vtemp = proxy({},vtemp), + imminent_EE_collision_vis = proxy({},imminent_EE_collision_vis), + imminent_EE_collision_buffer = proxy({},imminent_EE_collision_buffer)] ZS_LAMBDA(auto ci) mutable { + auto inds = imminent_EE_collision_buffer.pack(dim_c<4>,"inds",ci,int_c); + auto bary = imminent_EE_collision_buffer.pack(dim_c<4>,"bary",ci); + + vec3 ps[4] = {}; + for(int i = 0;i != 4;++i) + ps[i] = vtemp.pack(dim_c<3>,"x",inds[i]); + + auto pr = vec3::zeros(); + for(int i = 0;i != 4;++i) + pr += bary[i] * ps[i]; + + auto proja = vec3::zeros(); + auto projb = vec3::zeros(); + for(int i = 0;i != 2;++i) { + proja -= bary[i] * ps[i]; + projb += bary[i + 2] * ps[i + 2]; + } + + auto collision_normal = pr.normalized(); + + imminent_EE_collision_vis.tuple(dim_c<3>,"collision_normal",ci) = collision_normal; + imminent_EE_collision_vis.tuple(dim_c<3>,"pt",ci) = proja; + imminent_EE_collision_vis.tuple(dim_c<3>,"pp",ci) = projb; + }); + imminent_EE_collision_vis = imminent_EE_collision_vis.clone({zs::memsrc_e::host}); + + std::cout << "output EE VIS" << std::endl; + + auto prim_EE = std::make_shared(); + auto& vis_verts_EE = prim_EE->verts; + auto& vis_lines_EE = prim_EE->lines; + vis_verts_EE.resize(imminent_EE_collision_buffer.size() * 2); + vis_lines_EE.resize(imminent_EE_collision_buffer.size()); + + auto nrm_prim_EE = std::make_shared(); + auto& nrm_verts_EE = nrm_prim_EE->verts; + auto& nrm_lines_EE = nrm_prim_EE->lines; + nrm_verts_EE.resize(imminent_EE_collision_buffer.size() * 2); + nrm_lines_EE.resize(imminent_EE_collision_buffer.size()); + + ompPol(zs::range(imminent_EE_collision_buffer.size()),[ + &vis_verts_EE,&vis_lines_EE, + &nrm_verts_EE,&nrm_lines_EE, + imminent_EE_collision_vis = proxy({},imminent_EE_collision_vis)] (int ci) mutable { + auto cnrm = imminent_EE_collision_vis.pack(dim_c<3>,"collision_normal",ci); + auto pt = imminent_EE_collision_vis.pack(dim_c<3>,"pt",ci); + auto pp = imminent_EE_collision_vis.pack(dim_c<3>,"pp",ci); + auto pn = pp + cnrm; + + vis_verts_EE[ci * 2 + 0] = pp.to_array(); + vis_verts_EE[ci * 2 + 1] = pt.to_array(); + vis_lines_EE[ci] = zeno::vec2i{ci * 2 + 0,ci * 2 + 1}; + + nrm_verts_EE[ci * 2 + 0] = pp.to_array(); + nrm_verts_EE[ci * 2 + 1] = pn.to_array(); + nrm_lines_EE[ci] = zeno::vec2i{ci * 2 + 0,ci * 2 + 1}; + }); + + set_output("prim_EE",std::move(prim_EE)); + set_output("cnrm_EE",std::move(nrm_prim_EE)); + + } +}; + +ZENDEFNODE(VisualizeImminentCollision, {{{"zsparticles"}, + {"string","current_x_tag","x"}, + {"string","previous_x_tag","px"}, + // {"string","pscaleTag","pscale"}, + // {"float","repeling_strength","1.0"}, + {"float","immc_thickness","0.01"}, + // {"int","nm_imminent_iters","1"}, + // {"float","imm_restitution","0.1"}, + // {"float","imm_relaxation","0.25"}, + // {"bool","add_repulsion_force","0"}, + }, + {{"prim_PT"},{"cnrm_PT"},{"prim_EE"},{"cnrm_EE"}}, + {}, + {"PBD"}}); + + +struct DetangleCCDCollision : INode { + using T = float; + using vec3 = zs::vec; + using vec4 = zs::vec; + using vec4i = zs::vec; + using dtiles_t = zs::TileVector; + + virtual void apply() override { + using namespace zs; + constexpr auto space = execspace_e::cuda; + auto cudaPol = cuda_exec(); + using lbvh_t = typename ZenoLinearBvh::lbvh_t; + using bv_t = typename ZenoLinearBvh::lbvh_t::Box; + constexpr auto exec_tag = wrapv{}; + constexpr auto eps = (T)1e-7; + // constexpr auto MAX_PT_COLLISION_PAIRS = 1000000; + + auto zsparticles = get_input("zsparticles"); + auto current_x_tag = get_input2("current_x_tag"); + auto pre_x_tag = get_input2("previous_x_tag"); + + auto restitution_rate = get_input2("restitution"); + auto relaxation_rate = get_input2("relaxation"); + + auto thickness = get_input2("thickness"); + + auto& verts = zsparticles->getParticles(); + const auto& tris = zsparticles->getQuadraturePoints(); + const auto &edges = (*zsparticles)[ZenoParticles::s_surfEdgeTag]; + + dtiles_t vtemp(verts.get_allocator(),{ + {"x",3}, + {"v",3}, + {"minv",1} + },(size_t)verts.size()); + + auto nm_ccd_iters = get_input2("nm_ccd_iters"); + + cudaPol(zs::range(verts.size()),[ + verts = proxy({},verts), + vtemp = proxy({},vtemp), + current_x_tag = zs::SmallString(current_x_tag), + pre_x_tag = zs::SmallString(pre_x_tag)] ZS_LAMBDA(int vi) mutable { + vtemp.tuple(dim_c<3>,"x",vi) = verts.pack(dim_c<3>,pre_x_tag,vi); + vtemp.tuple(dim_c<3>,"v",vi) = verts.pack(dim_c<3>,current_x_tag,vi) - verts.pack(dim_c<3>,pre_x_tag,vi); + vtemp("minv",vi) = verts("minv",vi); + }); + + + lbvh_t triBvh{},eBvh{}; + + zs::Vector impulse_buffer{verts.get_allocator(),verts.size()}; + zs::Vector impulse_count{verts.get_allocator(),verts.size()}; + + auto do_ee_detection = get_input2("do_ee_detection"); + auto do_pt_detection = get_input2("do_pt_detection"); + + zs::Vector nm_ccd_collision{verts.get_allocator(),1}; + + std::cout << "resolve continous collision " << std::endl; + + auto res_threshold = thickness * 0.01; + res_threshold = res_threshold < 1e-3 ? 1e-3 : res_threshold; + + for(int iter = 0;iter != nm_ccd_iters;++iter) { + + cudaPol(zs::range(impulse_buffer),[]ZS_LAMBDA(auto& imp) mutable {imp = vec3::uniform(0);}); + cudaPol(zs::range(impulse_count),[]ZS_LAMBDA(auto& c) mutable {c = 0;}); + + nm_ccd_collision.setVal(0); + + if(do_pt_detection) { + // std::cout << "do continous self PT cololision impulse" << std::endl; + + auto do_bvh_refit = iter > 0; + COLLISION_UTILS::calc_continous_self_PT_collision_impulse(cudaPol, + verts, + vtemp,"x","v", + tris, + // thickness, + triBvh, + do_bvh_refit, + impulse_buffer, + impulse_count); + } + + if(do_ee_detection) { + // std::cout << "do continous self EE cololision impulse" << std::endl; + auto do_bvh_refit = iter > 0; + COLLISION_UTILS::calc_continous_self_EE_collision_impulse(cudaPol, + verts, + vtemp,"x","v", + edges, + eBvh, + do_bvh_refit, + impulse_buffer, + impulse_count); + } + + // std::cout << "apply CCD impulse" << std::endl; + cudaPol(zs::range(verts.size()),[ + verts = proxy({},verts), + vtemp = proxy({},vtemp), + impulse_buffer = proxy(impulse_buffer), + impulse_count = proxy(impulse_count), + relaxation_rate = relaxation_rate, + nm_ccd_collision = proxy(nm_ccd_collision), + res_threshold = res_threshold, + eps = eps, + thickness = thickness, + exec_tag = exec_tag] ZS_LAMBDA(int vi) mutable { + if(impulse_count[vi] == 0) + return; + if(impulse_buffer[vi].norm() < eps) + return; + + auto impulse = relaxation_rate * impulse_buffer[vi] / impulse_count[vi]; + if(impulse.norm() > res_threshold) + atomic_add(exec_tag,&nm_ccd_collision[0],1); + + // auto dv = impulse + vtemp.tuple(dim_c<3>,"v",vi) = vtemp.pack(dim_c<3>,"v",vi) + impulse; + // for(int i = 0;i != 3;++i) + // atomic_add(exec_tag,&vtemp("v",i,vi),dv[i]); + }); + + std::cout << "nm_ccd_collision : " << nm_ccd_collision.getVal() << std::endl; + if(nm_ccd_collision.getVal() == 0) + break; + } + // std::cout << "finish solving continous collision " << std::endl; + cudaPol(zs::range(verts.size()),[ + vtemp = proxy({},vtemp), + verts = proxy({},verts), + xtag = zs::SmallString(current_x_tag)] ZS_LAMBDA(int vi) mutable { + verts.tuple(dim_c<3>,xtag,vi) = vtemp.pack(dim_c<3>,"x",vi) + vtemp.pack(dim_c<3>,"v",vi); + }); + + set_output("zsparticles",zsparticles); + } +}; + +ZENDEFNODE(DetangleCCDCollision, {{{"zsparticles"}, + {"string","current_x_tag","x"}, + {"string","previous_x_tag","px"}, + {"int","nm_ccd_iters","1"}, + // {"string","pscaleTag","pscale"}, + {"float","thickness","0.1"}, + // {"float","immc_thickness","0.01"}, + // {"int","nm_imminent_iters","1"}, + {"float","restitution","0.1"}, + {"float","relaxation","1"}, + {"bool","do_ee_detection","1"}, + {"bool","do_pt_detection","1"}, + // {"bool","add_repulsion_force","0"}, + }, + {{"zsparticles"}}, + {}, + {"PBD"}}); + + +struct VisualizeContinousCollision : INode { + using T = float; + using vec3 = zs::vec; + using dtiles_t = zs::TileVector; + + virtual void apply() override { + using namespace zs; + using lbvh_t = typename ZenoLinearBvh::lbvh_t; + constexpr auto cuda_space = execspace_e::cuda; + auto cudaPol = cuda_exec(); + + constexpr auto omp_space = execspace_e::openmp; + auto ompPol = omp_exec(); + + auto zsparticles = get_input("zsparticles"); + auto current_x_tag = get_input2("current_x_tag"); + auto pre_x_tag = get_input2("previous_x_tag"); + + auto thickness = get_input2("thickness"); + + auto& verts = zsparticles->getParticles(); + const auto& tris = zsparticles->getQuadraturePoints(); + const auto &edges = (*zsparticles)[ZenoParticles::s_surfEdgeTag]; + + dtiles_t vtemp(verts.get_allocator(),{ + {"x",3}, + {"v",3}, + {"minv",1} + },(size_t)verts.size()); + + lbvh_t triBvh{},eBvh{}; + // auto nm_ccd_iters = get_input2("nm_ccd_iters"); + + cudaPol(zs::range(verts.size()),[ + verts = proxy({},verts), + vtemp = proxy({},vtemp), + current_x_tag = zs::SmallString(current_x_tag), + pre_x_tag = zs::SmallString(pre_x_tag)] ZS_LAMBDA(int vi) mutable { + vtemp.tuple(dim_c<3>,"x",vi) = verts.pack(dim_c<3>,pre_x_tag,vi); + vtemp.tuple(dim_c<3>,"v",vi) = verts.pack(dim_c<3>,current_x_tag,vi) - verts.pack(dim_c<3>,pre_x_tag,vi); + vtemp("minv",vi) = verts("minv",vi); + }); + + zs::Vector impulse_buffer{verts.get_allocator(),verts.size()}; + zs::Vector impulse_count{verts.get_allocator(),verts.size()}; + + cudaPol(zs::range(impulse_buffer),[]ZS_LAMBDA(auto& imp) mutable {imp = vec3::uniform(0);}); + cudaPol(zs::range(impulse_count),[]ZS_LAMBDA(auto& c) mutable {c = 0;}); + + COLLISION_UTILS::calc_continous_self_PT_collision_impulse(cudaPol, + verts, + vtemp,"x","v", + tris, + // thickness, + triBvh, + false, + impulse_buffer, + impulse_count); + + cudaPol(zs::range(impulse_buffer.size()),[ + impulse_buffer = proxy(impulse_buffer), + impulse_count = proxy(impulse_count)] ZS_LAMBDA(int vi) mutable { + if(impulse_count[vi] > 0) { + impulse_buffer[vi] = impulse_buffer[vi] / (T)impulse_count[vi]; + // printf("impulse[%d] : %f %f %f\n",vi + // ,(float)impulse_buffer[vi][0] + // ,(float)impulse_buffer[vi][1] + // ,(float)impulse_buffer[vi][2]); + } + }); + + dtiles_t ccd_PT_collision_vis(verts.get_allocator(),{ + {"impulse",3}, + {"p0",3}, + {"p1",3}, + {"pp",3} + },verts.size()); + + cudaPol(zs::range(verts.size()),[ + ccd_PT_collision_vis = proxy({},ccd_PT_collision_vis), + impulse_buffer = proxy(impulse_buffer), + vtemp = proxy({},vtemp)] ZS_LAMBDA(int vi) mutable { + ccd_PT_collision_vis.tuple(dim_c<3>,"impulse",vi) = impulse_buffer[vi]; + ccd_PT_collision_vis.tuple(dim_c<3>,"p0",vi) = vtemp.pack(dim_c<3>,"x",vi); + ccd_PT_collision_vis.tuple(dim_c<3>,"p1",vi) = vtemp.pack(dim_c<3>,"x",vi) + vtemp.pack(dim_c<3>,"v",vi); + ccd_PT_collision_vis.tuple(dim_c<3>,"pp",vi) = vtemp.pack(dim_c<3>,"x",vi) + vtemp.pack(dim_c<3>,"v",vi) + impulse_buffer[vi]; + }); + + ccd_PT_collision_vis = ccd_PT_collision_vis.clone({zs::memsrc_e::host}); + auto prim_PT = std::make_shared(); + auto& vis_verts_PT = prim_PT->verts; + auto& vis_lines_PT = prim_PT->lines; + vis_verts_PT.resize(verts.size() * 2); + vis_lines_PT.resize(verts.size()); + + auto scale = get_input2("scale"); + + ompPol(zs::range(verts.size()),[ + &vis_verts_PT,&vis_lines_PT, + scale = scale, + ccd_PT_collision_vis = proxy({},ccd_PT_collision_vis)] (int vi) mutable { + auto p = ccd_PT_collision_vis.pack(dim_c<3>,"p0",vi); + auto impulse = ccd_PT_collision_vis.pack(dim_c<3>,"impulse",vi); + auto pc = p + impulse * scale; + vis_verts_PT[vi * 2 + 0] = p.to_array(); + vis_verts_PT[vi * 2 + 1] = pc.to_array(); + vis_lines_PT[vi] = zeno::vec2i{vi * 2 + 0,vi * 2 + 1}; + }); + + set_output("impulse_PT",std::move(prim_PT)); + + cudaPol(zs::range(impulse_buffer),[]ZS_LAMBDA(auto& imp) mutable {imp = vec3::uniform(0);}); + cudaPol(zs::range(impulse_count),[]ZS_LAMBDA(auto& c) mutable {c = 0;}); + + COLLISION_UTILS::calc_continous_self_EE_collision_impulse(cudaPol, + verts, + vtemp,"x","v", + edges, + eBvh, + false, + impulse_buffer, + impulse_count); + + cudaPol(zs::range(impulse_buffer.size()),[ + impulse_buffer = proxy(impulse_buffer), + impulse_count = proxy(impulse_count)] ZS_LAMBDA(int vi) mutable { + if(impulse_count[vi] > 0) { + impulse_buffer[vi] = impulse_buffer[vi] / (T)impulse_count[vi]; + // printf("impulse[%d] : %f %f %f\n",vi + // ,(float)impulse_buffer[vi][0] + // ,(float)impulse_buffer[vi][1] + // ,(float)impulse_buffer[vi][2]); + } + }); + + dtiles_t ccd_EE_collision_vis(verts.get_allocator(),{ + {"impulse",3}, + {"p0",3}, + {"p1",3}, + {"pp",3} + },verts.size()); + + cudaPol(zs::range(verts.size()),[ + ccd_EE_collision_vis = proxy({},ccd_EE_collision_vis), + impulse_buffer = proxy(impulse_buffer), + vtemp = proxy({},vtemp)] ZS_LAMBDA(int vi) mutable { + ccd_EE_collision_vis.tuple(dim_c<3>,"impulse",vi) = impulse_buffer[vi]; + ccd_EE_collision_vis.tuple(dim_c<3>,"p0",vi) = vtemp.pack(dim_c<3>,"x",vi); + ccd_EE_collision_vis.tuple(dim_c<3>,"p1",vi) = vtemp.pack(dim_c<3>,"x",vi) + vtemp.pack(dim_c<3>,"v",vi); + ccd_EE_collision_vis.tuple(dim_c<3>,"pp",vi) = vtemp.pack(dim_c<3>,"x",vi) + vtemp.pack(dim_c<3>,"v",vi) + impulse_buffer[vi]; + }); + + ccd_EE_collision_vis = ccd_EE_collision_vis.clone({zs::memsrc_e::host}); + auto prim_EE = std::make_shared(); + auto& vis_verts_EE = prim_EE->verts; + auto& vis_lines_EE = prim_EE->lines; + vis_verts_EE.resize(verts.size() * 2); + vis_lines_EE.resize(verts.size()); + + ompPol(zs::range(verts.size()),[ + &vis_verts_EE,&vis_lines_EE, + scale = scale, + ccd_EE_collision_vis = proxy({},ccd_EE_collision_vis)] (int vi) mutable { + auto p = ccd_EE_collision_vis.pack(dim_c<3>,"p0",vi); + auto impulse = ccd_EE_collision_vis.pack(dim_c<3>,"impulse",vi); + auto pc = p + impulse * scale; + vis_verts_EE[vi * 2 + 0] = p.to_array(); + vis_verts_EE[vi * 2 + 1] = pc.to_array(); + vis_lines_EE[vi] = zeno::vec2i{vi * 2 + 0,vi * 2 + 1}; + }); + + set_output("impulse_EE",std::move(prim_EE)); + } +}; + +ZENDEFNODE(VisualizeContinousCollision, {{{"zsparticles"}, + {"string","current_x_tag","x"}, + {"string","previous_x_tag","px"}, + // {"string","pscaleTag","pscale"}, + // {"float","repeling_strength","1.0"}, + {"float","thickness","0.01"}, + // {"int","nm_imminent_iters","1"}, + // {"float","imm_restitution","0.1"}, + {"float","scale","0.25"}, + // {"bool","add_repulsion_force","0"}, + }, + {{"impulse_PT"},{"impulse_EE"}}, + {}, + {"PBD"}}); + +}; \ No newline at end of file diff --git a/projects/CuLagrange/pbd/constraint_function_kernel/constraint.cuh b/projects/CuLagrange/pbd/constraint_function_kernel/constraint.cuh index b0cfc69627..9215cde901 100644 --- a/projects/CuLagrange/pbd/constraint_function_kernel/constraint.cuh +++ b/projects/CuLagrange/pbd/constraint_function_kernel/constraint.cuh @@ -1,90 +1,1194 @@ #pragma once +#include "../../geometry/kernel/geo_math.hpp" +#include "zensim/math/MathUtils.h" + namespace zeno { namespace CONSTRAINT { +// FOR CLOTH SIMULATION + template + constexpr bool solve_DistanceConstraint( + const VECTOR3d &p0, SCALER invMass0, + const VECTOR3d &p1, SCALER invMass1, + const SCALER& restLength, + const SCALER& stiffness, + const SCALER& dt, + SCALER& lambda, + VECTOR3d &corr0, VECTOR3d &corr1) + { + SCALER K = invMass0 + invMass1; + VECTOR3d n = p0 - p1; + SCALER d = n.norm(); + SCALER C = d - restLength; + if (d > static_cast(1e-6)) + n /= d; + else + { + corr0 = VECTOR3d::uniform(0); + corr1 = VECTOR3d::uniform(0); + return false; + } + + SCALER alpha = 0.0; + if (stiffness != 0.0) + { + alpha = static_cast(1.0) / (stiffness * dt * dt); + K += alpha; + } - // template - // constexpr bool edge_length_constraint_predicate(const VECTOR3d x[2], - // const SCALER& rl) - // { - // auto edge = x[0] - x[1]; - // auto en = edge.norm(); - // return en > rl; - // } + SCALER Kinv = 0.0; + if (zs::abs(K) > static_cast(1e-6)) + Kinv = static_cast(1.0) / K; + else + { + corr0 = VECTOR3d::uniform(0); + corr1 = VECTOR3d::uniform(0); + return false; + } + + const SCALER delta_lambda = -Kinv * (C + alpha * lambda); + lambda += delta_lambda; + const VECTOR3d pt = n * delta_lambda; + + corr0 = invMass0 * pt; + corr1 = -invMass1 * pt; + return true; + } template - constexpr void edge_length_constraint_projection(const VECTOR3d x[2], - const SCALER& rl, - const SCALER inv_m[2], - const SCALER& compliance, - VECTOR3d dx[2]) { - auto edge = x[0] - x[1]; - auto en = edge.norm(); - edge /= (en + (SCALER)1e-6); - auto C = en - rl; - auto w = inv_m[0] + inv_m[1]; - auto s = -C / (w + compliance); - - dx[0] = edge * s * inv_m[0]; - dx[1] = -edge * s * inv_m[1]; + constexpr bool solve_DistanceConstraint( + const VECTOR3d &p0, SCALER invMass0, + const VECTOR3d &p1, SCALER invMass1, + const SCALER expectedDistance, + const SCALER stiffness, + VECTOR3d &corr0, VECTOR3d &corr1){ + VECTOR3d diff = p0 - p1; + SCALER distance = diff.norm(); + + if (zs::abs((distance - expectedDistance)) > static_cast(1e-5) && (invMass0 + invMass1) > static_cast(1e-5)){ + VECTOR3d gradient = diff / (distance + static_cast(1e-6)); + SCALER denom = invMass0 + invMass1; + SCALER lambda = (distance - expectedDistance) /denom; + auto common = stiffness * lambda * gradient; + // auto common = lambda * gradient; + corr0 = -invMass0 * common; + corr1 = invMass1 * common; + return false; + }else{ + corr0 = VECTOR3d::uniform(0); + corr1 = VECTOR3d::uniform(0); + } + + return true; } + + // ---------------------------------------------------------------------------------------------- template - constexpr void tet_volume_constraint_projection(const VECTOR3d x[4], - const SCALER& rv, - const SCALER inv_m[4], - const SCALER& compliance, - VECTOR3d dx[4]) { - dx[0] = (x[1] - x[2]).cross(x[3] - x[2]); - dx[1] = (x[2] - x[0]).cross(x[3] - x[0]); - dx[2] = (x[0] - x[1]).cross(x[3] - x[1]); - dx[3] = (x[1] - x[0]).cross(x[2] - x[0]); - - SCALER w = 0; - for(int i = 0;i != 4;++i) - w += dx[i].l2NormSqr() * inv_m[i]; - SCALER vol = zs::abs(x[1] - x[0]).cross(x[2] - x[0]).dot(x[3] - x[0]) / (SCALER)6; - SCALER C = (vol - rv) * (SCALER)6; - SCALER s = -C / (w + compliance); + constexpr bool solve_VolumeConstraint( + const VECTOR3d& p0, SCALER invMass0, + const VECTOR3d& p1, SCALER invMass1, + const VECTOR3d& p2, SCALER invMass2, + const VECTOR3d& p3, SCALER invMass3, + const SCALER restVolume, + const SCALER stiffness, + const SCALER dt, + SCALER& lambda, + VECTOR3d& corr0, VECTOR3d& corr1, VECTOR3d& corr2, VECTOR3d& corr3) + { + constexpr SCALER eps = (SCALER)1e-6; + SCALER volume = static_cast(1.0 / 6.0) * (p1 - p0).cross(p2 - p0).dot(p3 - p0); - for(int i = 0;i != 4;++i) - dx[i] = dx[i] * s * inv_m[i]; + corr0 = VECTOR3d::uniform(0); corr1 = VECTOR3d::uniform(0); corr2 = VECTOR3d::uniform(0); corr3 = VECTOR3d::uniform(0); + + VECTOR3d grad0 = (p1 - p2).cross(p3 - p2); + VECTOR3d grad1 = (p2 - p0).cross(p3 - p0); + VECTOR3d grad2 = (p0 - p1).cross(p3 - p1); + VECTOR3d grad3 = (p1 - p0).cross(p2 - p0); + + SCALER K = + invMass0 * grad0.l2NormSqr() + + invMass1 * grad1.l2NormSqr() + + invMass2 * grad2.l2NormSqr() + + invMass3 * grad3.l2NormSqr(); + + SCALER alpha = 0.0; + if (stiffness != 0.0) + { + alpha = static_cast(1.0) / (stiffness * dt * dt); + K += alpha; + } + + if (zs::abs(K) < eps) + return false; + + const SCALER C = volume - restVolume; + const SCALER delta_lambda = -(C + alpha * lambda) / K; + lambda += delta_lambda; + + corr0 = delta_lambda * invMass0 * grad0; + corr1 = delta_lambda * invMass1 * grad1; + corr2 = delta_lambda * invMass2 * grad2; + corr3 = delta_lambda * invMass3 * grad3; + + return true; + } + + template + constexpr bool init_DihedralBendingConstraint( + const VECTOR3d& p0, + const VECTOR3d& p1, + const VECTOR3d& p2, + const VECTOR3d& p3, + SCALER& restAngle){ + VECTOR3d e = p3 - p2; + SCALER elen = e.norm(); + if (elen < 1e-4) + return false; + + SCALER invElen = static_cast(1.0) / elen; + + VECTOR3d n1 = LSL_GEO::facet_normal(p0,p2,p3); + VECTOR3d n2 = LSL_GEO::facet_normal(p1,p3,p2); + + SCALER n12 = n1.dot(n2); + SCALER angle = 0; + if((1 - n12) > 1e-6) + angle = zs::sqrt((1 - n12) / 2); + if(n1.cross(n2).dot(e) < 0) + angle = -angle; + restAngle = angle; + return true; } - // edge0 = [0,2,1] - // edge1 = [0,1,3] + template - constexpr void tri_bending_constraint_projection(const VECTOR3d x[4], - const SCALER& rda, - const SCALER inv_m[4], - const SCALER& compliance, - VECTOR3d dx[4]) { - VECTOR3d p[4]; - for(int i = 0;i != 4;++i) - p[i] = x[i] - x[0]; - auto p12 = p[1].cross(p[2]); - auto p13 = p[1].cross(p[3]); - auto n0 = p12 / (p23.norm() + (SCALER)1e-6); - auto n1 = p13 / (p12.norm() + (SCALER)1e-6); + constexpr bool solve_DihedralConstraint( + const VECTOR3d &p0,const SCALER& invMass0, + const VECTOR3d &p1,const SCALER& invMass1, + const VECTOR3d &p2,const SCALER& invMass2, + const VECTOR3d &p3,const SCALER& invMass3, + const SCALER& restAngle, + const SCALER& stiffness, + VECTOR3d &corr0, VECTOR3d &corr1, VECTOR3d &corr2, VECTOR3d &corr3) + { + constexpr SCALER eps = static_cast(1e-6); + if (invMass0 == 0.0 && invMass1 == 0.0) + return false; + + VECTOR3d e = p3-p2; + SCALER elen = e.norm(); + if (elen < eps) + return false; + + SCALER invElen = static_cast(1.0) / elen; + + // auto n1 = LSL_GEO::facet_normal(p0,p2,p3); + // auto n2 = LSL_GEO::facet_normal(p1,p3,p2); + VECTOR3d n1 = (p2 - p0).cross(p3 - p0); n1 /= n1.l2NormSqr(); + VECTOR3d n2 = (p3 - p1).cross(p2 - p1); n2 /= n2.l2NormSqr(); + + VECTOR3d d0 = elen*n1; + VECTOR3d d1 = elen*n2; + VECTOR3d d2 = (p0-p3).dot(e) * invElen * n1 + (p1-p3).dot(e) * invElen * n2; + VECTOR3d d3 = (p2-p0).dot(e) * invElen * n1 + (p2-p1).dot(e) * invElen * n2; + + // SCALER phi = (-0.6981317 * dot * dot - 0.8726646) * dot + 1.570796; // fast approximation + n1 = n1.normalized(); + n2 = n2.normalized(); + SCALER n12 = n1.dot(n2); + SCALER angle = 0; + if((1 - n12) > 1e-6) + angle = zs::sqrt((1 - n12) / 2); + if(n1.cross(n2).dot(e) < 0) + angle = -angle; + + SCALER lambda = + invMass0 * d0.l2NormSqr() + + invMass1 * d1.l2NormSqr() + + invMass2 * d2.l2NormSqr() + + invMass3 * d3.l2NormSqr(); + + if (lambda == 0.0) + return false; + + // stability + // 1.5 is the largest magic number I found to be stable in all cases :-) + //if (stiffness > 0.5 && fabs(phi - b.restAngle) > 1.5) + // stiffness = 0.5; + + lambda = (angle - restAngle) / lambda * stiffness; + + // if (n1.cross(n2).dot(e) > 0.0) + // lambda = -lambda; + + corr0 = invMass0 * lambda * d0; + corr1 = invMass1 * lambda * d1; + corr2 = invMass2 * lambda * d2; + corr3 = invMass3 * lambda * d3; + + return true; + } - auto d = n1.dot(n0); - auto p12n = p12.norm(); - auto p13n = p13.norm(); + template + constexpr bool solve_DihedralConstraint( + const VECTOR3d& p0, const SCALER& invMass0, + const VECTOR3d& p1, const SCALER& invMass1, + const VECTOR3d& p2, const SCALER& invMass2, + const VECTOR3d& p3, const SCALER& invMass3, + const SCALER& ra, + const SCALER& stiffness, + const SCALER& dt, + SCALER& lambda, + VECTOR3d& corr0, VECTOR3d& corr1, VECTOR3d& corr2, VECTOR3d& corr3){ + constexpr SCALER eps = static_cast(1e-4); - VECTOR3d q[4]; + auto e = p3 - p2; + auto elen = e.norm(); + if(elen < eps) + return false; + + SCALER invElen = static_cast(1.0) / elen; - auto q[2] = (p[1].cross(n1) + n0.cross(p[1]) * d)/p12n; - auto q[3] = (p[1].cross(n0) + n1.cross(p[1]) * d)/p13n; - auto q[1] = -(p[2].cross(n1) + n0.cross(p[2]) *d)/p12n - (p[3].cross(n0) + n1.cross(p[3]) * d)/p13n; - auto q[0] = -q[1] - q[2] - q[3]; + VECTOR3d n1 = (p2 - p0).cross(p3 - p0); n1 /= n1.l2NormSqr(); + VECTOR3d n2 = (p3 - p1).cross(p2 - p1); n2 /= n2.l2NormSqr(); - auto C = zs::acos(d) - rda; - SCALER w = 0; - for(int i = 0;i != 4;++i) - w += q[i].l2NormSqr() * inv_m[i]; - auto s = -C * zs::sqrt(1 - d * d) / (w + compliance); + VECTOR3d gradC[4] = {}; + gradC[0] = elen*n1; + gradC[1] = elen*n2; + gradC[2] = (p0-p3).dot(e) * invElen * n1 + (p1-p3).dot(e) * invElen * n2; + gradC[3] = (p2-p0).dot(e) * invElen * n1 + (p2-p1).dot(e) * invElen * n2; + + n1 = n1.normalized(); + n2 = n2.normalized(); + SCALER n12 = n1.dot(n2); + SCALER angle = 0; + if((1 - n12) > 1e-6) + angle = zs::sqrt((1 - n12) / 2); + if(n1.cross(n2).dot(e) < 0) + angle = -angle; + + SCALER alpha = 0.0; + if (stiffness != 0.0) + alpha = static_cast(1.0) / (stiffness * dt * dt); + + + SCALER sum_normGradC = + invMass0 * gradC[0].l2NormSqr() + + invMass1 * gradC[1].l2NormSqr() + + invMass2 * gradC[2].l2NormSqr() + + invMass3 * gradC[3].l2NormSqr() + alpha; + + if(sum_normGradC < eps) + return false; + + auto energy = angle - ra; + + // compute impulse-based scaling factor + SCALER delta_lambda = -(energy + alpha * lambda) / sum_normGradC; + lambda += delta_lambda; + + // if(n1.cross(n2).dot(e) > 0.0) + // delta_lambda = -delta_lambda; + corr0 = (delta_lambda * invMass0) * gradC[0]; + corr1 = (delta_lambda * invMass1) * gradC[1]; + corr2 = (delta_lambda * invMass2) * gradC[2]; + corr3 = (delta_lambda * invMass3) * gradC[3]; + return true; + } + +// ---------------------------------------------------------------------------------------------- + template + constexpr bool init_IsometricBendingConstraint( + const VECTOR3d& p0, + const VECTOR3d& p1, + const VECTOR3d& p2, + const VECTOR3d& p3, + MATRIX4d& Q) + { + using SCALER = typename VECTOR3d::value_type; + // Compute matrix Q for quadratic bending + const VECTOR3d x[4] = { p2, p3, p0, p1 }; + // Q = MATRIX4d::uniform(0); + + // const auto e0 = x[1].cast() - x[0].cast(); + // const auto e1 = x[2].cast() - x[0].cast(); + // const auto e2 = x[3].cast() - x[0].cast(); + // const auto e3 = x[2].cast() - x[1].cast(); + // const auto e4 = x[3].cast() - x[1].cast(); + + const auto e0 = x[1].cast() - x[0].cast(); + const auto e1 = x[2].cast() - x[0].cast(); + const auto e2 = x[3].cast() - x[0].cast(); + const auto e3 = x[2].cast() - x[1].cast(); + const auto e4 = x[3].cast() - x[1].cast(); + + + // auto e0 = e0_.cast(); + // auto e1 = e1_.cast(); + // auto e2 = e2_.cast(); + // auto e3 = e3_.cast(); + // auto e4 = e4_.cast(); + + // printf("init isometric bending energy : %f %f %f %f\n", + // (float)p0.norm(), + // (float)p1.norm(), + // (float)p2.norm(), + // (float)p3.norm()); + + const double c01 = LSL_GEO::cotTheta(e0, e1); + const double c02 = LSL_GEO::cotTheta(e0, e2); + const double c03 = LSL_GEO::cotTheta(-e0, e3); + const double c04 = LSL_GEO::cotTheta(-e0, e4); + + const double A0 = static_cast(0.5) * (e0.cross(e1)).norm(); + const double A1 = static_cast(0.5) * (e0.cross(e2)).norm(); + + const double coef = static_cast(-3.0 / 2.0) / (A0 + A1); + const double K[4] = { c03 + c04, c01 + c02, -c01 - c03, -c02 - c04 }; + const double K2[4] = { coef * K[0], coef * K[1], coef * K[2], coef * K[3] }; + + for (unsigned char j = 0; j < 4; j++) + { + for (unsigned char k = 0; k < j; k++) + { + Q(j, k) = Q(k, j) = (SCALER)(K[j] * K2[k]); + } + Q(j, j) = (SCALER)(K[j] * K2[j]); + } + + return true; + } +// ---------------------------------------------------------------------------------------------- + template + constexpr bool solve_IsometricBendingConstraint( + const VECTOR3d& p0, const SCALER& invMass0, + const VECTOR3d& p1, const SCALER& invMass1, + const VECTOR3d& p2, const SCALER& invMass2, + const VECTOR3d& p3, const SCALER& invMass3, + const MATRIX4d& Q, + const SCALER& stiffness, + const SCALER& dt, + SCALER& lambda, + VECTOR3d& corr0, VECTOR3d& corr1, VECTOR3d& corr2, VECTOR3d& corr3) + { + constexpr SCALER eps = static_cast(1e-4); + const VECTOR3d x[4] = { p2, p3, p0, p1 }; + SCALER invMass[4] = { invMass2, invMass3, invMass0, invMass1 }; + + SCALER energy = 0.0; + for (unsigned char k = 0; k < 4; k++) + for (unsigned char j = 0; j < 4; j++) + energy += Q(j, k) * (x[k].dot(x[j])); + energy *= static_cast(0.5); + + // printf("isometric_bending_energy : %f\n",(float)energy); + + // printf("solve isometric bending energy : %f %f %f %f\n", + // (float)p0.norm(), + // (float)p1.norm(), + // (float)p2.norm(), + // (float)p3.norm()); + + VECTOR3d gradC[4] = {}; + gradC[0] = VECTOR3d::uniform(0); + gradC[1] = VECTOR3d::uniform(0); + gradC[2] = VECTOR3d::uniform(0); + gradC[3] = VECTOR3d::uniform(0); + for (unsigned char k = 0; k < 4; k++) + for (unsigned char j = 0; j < 4; j++) + gradC[j] += Q(j, k) * x[k]; + + + SCALER sum_normGradC = 0.0; + for (unsigned int j = 0; j < 4; j++) + { + // compute sum of squared gradient norms + if (invMass[j] != 0.0) + sum_normGradC += invMass[j] * gradC[j].l2NormSqr(); + } + + SCALER alpha = 0.0; + if (stiffness != 0.0) + { + alpha = static_cast(1.0) / (stiffness * dt * dt); + sum_normGradC += alpha; + } + + // exit early if required + + + if (sum_normGradC > eps) + { + // compute impulse-based scaling factor + SCALER delta_lambda = -(energy + alpha * lambda) / sum_normGradC; + lambda += delta_lambda; + + corr0 = (delta_lambda * invMass[2]) * gradC[2]; + corr1 = (delta_lambda * invMass[3]) * gradC[3]; + corr2 = (delta_lambda * invMass[0]) * gradC[0]; + corr3 = (delta_lambda * invMass[1]) * gradC[1]; + // printf("update corr for iso_bending energy\n"); + + auto gradCSum = (float)0; for(int i = 0;i != 4;++i) - dx[i] = q[i] * s * inv_m[i]; + gradCSum += gradC[i].norm(); + if(gradCSum > 1e-4) { + // printf("gradC : %f %f %f %f corr : %f %f %f %f\n", + // (float)gradC[0].norm(),(float)gradC[1].norm(),(float)gradC[2].norm(),(float)gradC[3].norm(), + // (float)corr0.norm(),(float)corr1.norm(),(float)corr2.norm(),(float)corr3.norm()); + } + + return true; + }else { + return false; + } + } + + + template + constexpr bool solve_IsometricBendingConstraint( + const VECTOR3d& p0, SCALER invMass0, + const VECTOR3d& p1, SCALER invMass1, + const VECTOR3d& p2, SCALER invMass2, + const VECTOR3d& p3, SCALER invMass3, + const MATRIX4d& Q, + const SCALER& stiffness, + VECTOR3d& corr0, VECTOR3d& corr1, VECTOR3d& corr2, VECTOR3d& corr3){ + constexpr SCALER eps = static_cast(1e-6); + const VECTOR3d x[4] = { p2, p3, p0, p1 }; + SCALER invMass[4] = { invMass2, invMass3, invMass0, invMass1 }; + + SCALER energy = 0.0; + for (unsigned char k = 0; k < 4; k++) + for (unsigned char j = 0; j < 4; j++) + energy += Q(j, k) * (x[k].dot(x[j])); + energy *= 0.5; + + VECTOR3d gradC[4] = {}; + gradC[0] = VECTOR3d::uniform(0); + gradC[1] = VECTOR3d::uniform(0); + gradC[2] = VECTOR3d::uniform(0); + gradC[3] = VECTOR3d::uniform(0); + for (unsigned char k = 0; k < 4; k++) + for (unsigned char j = 0; j < 4; j++) + gradC[j] += Q(j, k) * x[k]; + + + SCALER sum_normGradC = 0.0; + for (unsigned int j = 0; j < 4; j++) + { + // compute sum of squared gradient norms + if (invMass[j] != 0.0) + sum_normGradC += invMass[j] * gradC[j].l2NormSqr(); + } + + // exit early if required + if (sum_normGradC > eps) + { + // compute impulse-based scaling factor + const SCALER s = -(energy)/ sum_normGradC; + + corr0 = stiffness * (s * invMass[2]) * gradC[2]; + corr1 = stiffness * (s * invMass[3]) * gradC[3]; + corr2 = stiffness * (s * invMass[0]) * gradC[0]; + corr3 = stiffness * (s * invMass[1]) * gradC[1]; + + + return true; + }else { + corr0 = VECTOR3d::uniform(0); + corr1 = VECTOR3d::uniform(0); + corr2 = VECTOR3d::uniform(0); + corr3 = VECTOR3d::uniform(0); + } + return false; + } + + template + constexpr bool solve_PlaneConstraint( + const VECTOR3d& p, SCALER invMass, + const VECTOR3d& root, + const VECTOR3d& nrm, + const SCALER& thickness, + const SCALER& stiffness, + const SCALER& dt, + SCALER& lambda, + VECTOR3d& dp) { + SCALER C = (p - root).dot(nrm) - thickness; + if(C > static_cast(1e-6)) { + dp = VECTOR3d::uniform(0); + return true; + } + + SCALER K = invMass * nrm.l2NormSqr(); + + SCALER alpha = 0.0; + if(stiffness != 0.0) { + alpha = static_cast(1.0) / (stiffness * dt * dt); + K += alpha; + } + + SCALER Kinv = 0.0; + if(zs::abs(K) > static_cast(1e-6)) + Kinv = static_cast(1.0) / K; + else + { + dp = VECTOR3d::uniform(0); + return true; + } + + const SCALER delta_lambda = -Kinv * (C + alpha * lambda); + lambda += delta_lambda; + const VECTOR3d pt = nrm * delta_lambda; + + dp = invMass * pt; + return true; + } + +// ---------------------------------------------------------------------------------------------- + template + constexpr bool solve_TrianglePointDistanceConstraint( + const VECTOR3d &p, SCALER invMass, + const VECTOR3d &p0, SCALER invMass0, + const VECTOR3d &p1, SCALER invMass1, + const VECTOR3d &p2, SCALER invMass2, + const SCALER restDist, + const SCALER compressionStiffness, + const SCALER stretchStiffness, + SCALER& lambda, + VECTOR3d &corr, VECTOR3d &corr0, VECTOR3d &corr1, VECTOR3d &corr2) + { + // find barycentric coordinates of closest point on triangle + + SCALER b0 = static_cast(1.0 / 3.0); // for singular case + SCALER b1 = b0; + SCALER b2 = b0; + + VECTOR3d d1 = p1 - p0; + VECTOR3d d2 = p2 - p0; + VECTOR3d pp0 = p - p0; + SCALER a = d1.dot(d1); + SCALER b = d2.dot(d1); + SCALER c = pp0.dot(d1); + SCALER d = b; + SCALER e = d2.dot(d2); + SCALER f = pp0.dot(d2); + SCALER det = a*e - b*d; + + if (det != 0.0) { + SCALER s = (c*e - b*f) / det; + SCALER t = (a*f - c*d) / det; + b0 = static_cast(1.0) - s - t; // inside triangle + b1 = s; + b2 = t; + if (b0 < 0.0) { // on edge 1-2 + VECTOR3d d = p2 - p1; + SCALER d2 = d.dot(d); + SCALER t = (d2 == static_cast(0.0)) ? static_cast(0.5) : d.dot(p - p1) / d2; + if (t < 0.0) t = 0.0; // on point 1 + if (t > 1.0) t = 1.0; // on point 2 + b0 = 0.0; + b1 = (static_cast(1.0) - t); + b2 = t; + } + else if (b1 < 0.0) { // on edge 2-0 + VECTOR3d d = p0 - p2; + SCALER d2 = d.dot(d); + SCALER t = (d2 == static_cast(0.0)) ? static_cast(0.5) : d.dot(p - p2) / d2; + if (t < 0.0) t = 0.0; // on point 2 + if (t > 1.0) t = 1.0; // on point 0 + b1 = 0.0; + b2 = (static_cast(1.0) - t); + b0 = t; + } + else if (b2 < 0.0) { // on edge 0-1 + VECTOR3d d = p1 - p0; + SCALER d2 = d.dot(d); + SCALER t = (d2 == static_cast(0.0)) ? static_cast(0.5) : d.dot(p - p0) / d2; + if (t < 0.0) t = 0.0; // on point 0 + if (t > 1.0) t = 1.0; // on point 1 + b2 = 0.0; + b0 = (static_cast(1.0) - t); + b1 = t; + } + } + VECTOR3d q = p0 * b0 + p1 * b1 + p2 * b2; + VECTOR3d n = p - q; + SCALER dist = n.norm(); + n.normalize(); + SCALER C = dist - restDist; + VECTOR3d grad = n; + VECTOR3d grad0 = -n * b0; + VECTOR3d grad1 = -n * b1; + VECTOR3d grad2 = -n * b2; + + SCALER s = invMass + invMass0 * b0*b0 + invMass1 * b1*b1 + invMass2 * b2*b2; + if (s == 0.0) + return false; + + s = C / s; + if (C < 0.0) + s *= compressionStiffness; + else + s *= stretchStiffness; + + if (s == 0.0) + return false; + + corr = -s * invMass * grad; + corr0 = -s * invMass0 * grad0; + corr1 = -s * invMass1 * grad1; + corr2 = -s * invMass2 * grad2; + return true; } + // ---------------------------------------------------------------------------------------------- + template + constexpr bool solve_EdgeEdgeDistanceConstraint( + const VECTOR3d &p0, SCALER invMass0, + const VECTOR3d &p1, SCALER invMass1, + const VECTOR3d &p2, SCALER invMass2, + const VECTOR3d &p3, SCALER invMass3, + const SCALER restDist, + const SCALER compressionStiffness, + const SCALER stretchStiffness, + SCALER& lambda, + VECTOR3d &corr0, VECTOR3d &corr1, VECTOR3d &corr2, VECTOR3d &corr3) + { + VECTOR3d d0 = p1 - p0; + VECTOR3d d1 = p3 - p2; + + SCALER a = d0.l2NormSqr(); + SCALER b = -d0.dot(d1); + SCALER c = d0.dot(d1); + SCALER d = -d1.l2NormSqr(); + SCALER e = (p2 - p0).dot(d0); + SCALER f = (p2 - p0).dot(d1); + SCALER det = a*d - b*c; + SCALER s, t; + if (det != 0.0) { + det = static_cast(1.0) / det; + s = (e*d - b*f) * det; + t = (a*f - e*c) * det; + } + else { // d0 and d1 parallel + SCALER s0 = p0.dot(d0); + SCALER s1 = p1.dot(d0); + SCALER t0 = p2.dot(d0); + SCALER t1 = p3.dot(d0); + bool flip0 = false; + bool flip1 = false; + + if (s0 > s1) { SCALER f = s0; s0 = s1; s1 = f; flip0 = true; } + if (t0 > t1) { SCALER f = t0; t0 = t1; t1 = f; flip1 = true; } + + if (s0 >= t1) { + s = !flip0 ? static_cast(0.0) : static_cast(1.0); + t = !flip1 ? static_cast(1.0) : static_cast(0.0); + } + else if (t0 >= s1) { + s = !flip0 ? static_cast(1.0) : static_cast(0.0); + t = !flip1 ? static_cast(0.0) : static_cast(1.0); + } + else { // overlap + SCALER mid = (s0 > t0) ? (s0 + t1) * static_cast(0.5) : (t0 + s1) * static_cast(0.5); + s = (s0 == s1) ? static_cast(0.5) : (mid - s0) / (s1 - s0); + t = (t0 == t1) ? static_cast(0.5) : (mid - t0) / (t1 - t0); + } + } + if (s < 0.0) s = 0.0; + if (s > 1.0) s = 1.0; + if (t < 0.0) t = 0.0; + if (t > 1.0) t = 1.0; + + SCALER b0 = static_cast(1.0) - s; + SCALER b1 = s; + SCALER b2 = static_cast(1.0) - t; + SCALER b3 = t; + + VECTOR3d q0 = p0 * b0 + p1 * b1; + VECTOR3d q1 = p2 * b2 + p3 * b3; + VECTOR3d n = q0 - q1; + SCALER dist = n.norm(); + n.normalize(); + SCALER C = dist - restDist; + VECTOR3d grad0 = n * b0; + VECTOR3d grad1 = n * b1; + VECTOR3d grad2 = -n * b2; + VECTOR3d grad3 = -n * b3; + + s = invMass0 * b0*b0 + invMass1 * b1*b1 + invMass2 * b2*b2 + invMass3 * b3*b3; + if (s == 0.0) + return false; + + s = C / s; + if (C < 0.0) + s *= compressionStiffness; + else + s *= stretchStiffness; + + if (s == 0.0) + return false; + + corr0 = -s * invMass0 * grad0; + corr1 = -s * invMass1 * grad1; + corr2 = -s * invMass2 * grad2; + corr3 = -s * invMass3 * grad3; + return true; + } + +// FOR ELASTIC RODS SIMULATION +// ---------------------------------------------------------------------------------------------- +// template +// constexpr bool solve_StretchShearConstraint( +// const VECTOR3d& p0, SCALER invMass0, +// const VECTOR3d& p1, SCALER invMass1, +// const QUATERNION& q0, SCALER invMassq0, +// const VECTOR3d& stretchingAndShearingKs, +// const SCALER restLength, +// VECTOR3d& corr0, VECTOR3d& corr1, QUATERNION& corrq0) +// { +// VECTOR3d d3; //third director d3 = q0 * e_3 * q0_conjugate +// d3[0] = static_cast(2.0) * (q0.x() * q0.z() + q0.w() * q0.y()); +// d3[1] = static_cast(2.0) * (q0.y() * q0.z() - q0.w() * q0.x()); +// d3[2] = q0.w() * q0.w() - q0.x() * q0.x() - q0.y() * q0.y() + q0.z() * q0.z(); + +// VECTOR3d gamma = (p1 - p0) / restLength - d3; +// gamma /= (invMass1 + invMass0) / restLength + invMassq0 * static_cast(4.0)*restLength + eps; + +// if (std::abs(stretchingAndShearingKs[0] - stretchingAndShearingKs[1]) < eps && std::abs(stretchingAndShearingKs[0] - stretchingAndShearingKs[2]) < eps) //all Ks are approx. equal +// for (int i = 0; i<3; i++) gamma[i] *= stretchingAndShearingKs[i]; +// else //diffenent stretching and shearing Ks. Transform diag(Ks[0], Ks[1], Ks[2]) into world space using Ks_w = R(q0) * diag(Ks[0], Ks[1], Ks[2]) * R^T(q0) and multiply it with gamma +// { +// MATRIX3d R = q0.toRotationMatrix(); +// gamma = (R.transpose() * gamma).eval(); +// for (int i = 0; i<3; i++) gamma[i] *= stretchingAndShearingKs[i]; +// gamma = (R * gamma).eval(); +// } + +// corr0 = invMass0 * gamma; +// corr1 = -invMass1 * gamma; + +// QUATERNION q_e_3_bar(q0.z(), -q0.y(), q0.x(), -q0.w()); //compute q*e_3.conjugate (cheaper than quaternion product) +// corrq0 = QUATERNION(0.0, gamma.x(), gamma.y(), gamma.z()) * q_e_3_bar; +// corrq0.coeffs() *= static_cast(2.0) * invMassq0 * restLength; + +// return true; +// } + +// // ---------------------------------------------------------------------------------------------- +// template +// constexpr bool solve_BendTwistConstraint( +// const QUATERNION& q0, SCALER invMassq0, +// const QUATERNION& q1, SCALER invMassq1, +// const VECTOR3d& bendingAndTwistingKs, +// const QUATERNION& restDarbouxVector, +// QUATERNION& corrq0, QUATERNION& corrq1) +// { +// QUATERNION omega = q0.conjugate() * q1; //darboux vector + +// QUATERNION omega_plus; +// omega_plus.coeffs() = omega.coeffs() + restDarbouxVector.coeffs(); //delta Omega with -Omega_0 +// omega.coeffs() = omega.coeffs() - restDarbouxVector.coeffs(); //delta Omega with + omega_0 +// if (omega.l2NormSqr() > omega_plus.l2NormSqr()) omega = omega_plus; + +// for (int i = 0; i < 3; i++) omega.coeffs()[i] *= bendingAndTwistingKs[i] / (invMassq0 + invMassq1 + static_cast(1.0e-6)); +// omega.w() = 0.0; //discrete Darboux vector does not have vanishing scalar part + +// corrq0 = q1 * omega; +// corrq1 = q0 * omega; +// corrq0.coeffs() *= invMassq0; +// corrq1.coeffs() *= -invMassq1; +// return true; +// } + +// // ---------------------------------------------------------------------------------------------- +// template +// constexpr bool solve_PerpendiculaBisectorConstraint( +// const VECTOR3d &p0, SCALER invMass0, +// const VECTOR3d &p1, SCALER invMass1, +// const VECTOR3d &p2, SCALER invMass2, +// const SCALER stiffness, +// VECTOR3d &corr0, VECTOR3d &corr1, VECTOR3d &corr2) +// { +// const VECTOR3d pm = 0.5 * (p0 + p1); +// const VECTOR3d p0p2 = p0 - p2; +// const VECTOR3d p2p1 = p2 - p1; +// const VECTOR3d p1p0 = p1 - p0; +// const VECTOR3d p2pm = p2 - pm; + +// SCALER wSum = invMass0 * p0p2.l2NormSqr() + invMass1 * p2p1.l2NormSqr() + invMass2 * p1p0.l2NormSqr(); +// if (wSum < eps) +// return false; + +// const SCALER lambda = stiffness * p2pm.dot(p1p0) / wSum; + +// corr0 = -invMass0 * lambda * p0p2; +// corr1 = -invMass1 * lambda * p2p1; +// corr2 = -invMass2 * lambda * p1p0; + +// return true; +// } + +// // ---------------------------------------------------------------------------------------------- +// template +// constexpr bool solve_GhostPointEdgeDistanceConstraint( +// const VECTOR3d& p0, SCALER invMass0, +// const VECTOR3d& p1, SCALER invMass1, +// const VECTOR3d& p2, SCALER invMass2, +// const SCALER stiffness, +// const SCALER ghostEdgeRestLength, +// VECTOR3d& corr0, VECTOR3d& corr1, VECTOR3d& corr2) +// { +// // Ghost-Edge constraint +// VECTOR3d pm = 0.5 * (p0 + p1); +// VECTOR3d p2pm = p2 - pm; +// SCALER wSum = static_cast(0.25) * invMass0 + static_cast(0.25) * invMass1 + static_cast(1.0) * invMass2; + +// if (wSum < eps) +// return false; + +// SCALER p2pm_mag = p2pm.norm(); +// p2pm *= static_cast(1.0) / p2pm_mag; + +// const SCALER lambda = stiffness * (p2pm_mag - ghostEdgeRestLength) / wSum; + +// corr0 = 0.5 * invMass0 * lambda * p2pm; +// corr1 = 0.5 * invMass1 * lambda * p2pm; +// corr2 = -1.0 * invMass2 * lambda * p2pm; + +// return true; +// } + +// // ---------------------------------------------------------------------------------------------- +// template +// constexpr bool solve_DarbouxVectorConstraint( +// const VECTOR3d& p0, SCALER invMass0, +// const VECTOR3d& p1, SCALER invMass1, +// const VECTOR3d& p2, SCALER invMass2, +// const VECTOR3d& p3, SCALER invMass3, +// const VECTOR3d& p4, SCALER invMass4, +// const VECTOR3d& bendingAndTwistingKs, +// const SCALER midEdgeLength, +// const VECTOR3d& restDarbouxVector, +// VECTOR3d& corr0, VECTOR3d& corr1, VECTOR3d& corr2, VECTOR3d& corr3, VECTOR3d& corr4) +// { +// // Single rod element: +// // 3 4 //ghost points +// // | | +// // --0---1---2-- // rod points + +// VECTOR3d darboux_vector; +// MATRIX3d d0, d1; + +// computeMaterialFrame(p0, p1, p3, d0); +// computeMaterialFrame(p1, p2, p4, d1); + +// computeDarbouxVector(d0, d1, midEdgeLength, darboux_vector); + +// MATRIX3d dajpi[3][3]; +// computeMaterialFrameDerivative(p0, p1, p3, d0, +// dajpi[0][0], dajpi[0][1], dajpi[0][2], +// dajpi[1][0], dajpi[1][1], dajpi[1][2], +// dajpi[2][0], dajpi[2][1], dajpi[2][2]); + +// MATRIX3d dbjpi[3][3]; +// computeMaterialFrameDerivative(p1, p2, p4, d1, +// dbjpi[0][0], dbjpi[0][1], dbjpi[0][2], +// dbjpi[1][0], dbjpi[1][1], dbjpi[1][2], +// dbjpi[2][0], dbjpi[2][1], dbjpi[2][2]); + +// MATRIX3d constraint_jacobian[5]; +// computeDarbouxGradient( +// darboux_vector, midEdgeLength, d0, d1, +// dajpi, dbjpi, +// //bendingAndTwistingKs, +// constraint_jacobian[0], +// constraint_jacobian[1], +// constraint_jacobian[2], +// constraint_jacobian[3], +// constraint_jacobian[4]); + +// const VECTOR3d constraint_value(bendingAndTwistingKs[0] * (darboux_vector[0] - restDarbouxVector[0]), +// bendingAndTwistingKs[1] * (darboux_vector[1] - restDarbouxVector[1]), +// bendingAndTwistingKs[2] * (darboux_vector[2] - restDarbouxVector[2])); + +// MATRIX3d factor_matrix; +// factor_matrix = VECTOR3d::uniform(0); + +// MATRIX3d tmp_mat; +// SCALER invMasses[]{ invMass0, invMass1, invMass2, invMass3, invMass4 }; +// for (int i = 0; i < 5; ++i) +// { +// tmp_mat = constraint_jacobian[i].transpose() * constraint_jacobian[i]; +// tmp_mat.col(0) *= invMasses[i]; +// tmp_mat.col(1) *= invMasses[i]; +// tmp_mat.col(2) *= invMasses[i]; + +// factor_matrix += tmp_mat; +// } + +// VECTOR3d dp[5]; +// tmp_mat = factor_matrix.inverse(); + +// for (int i = 0; i < 5; ++i) +// { +// constraint_jacobian[i].col(0) *= invMasses[i]; +// constraint_jacobian[i].col(1) *= invMasses[i]; +// constraint_jacobian[i].col(2) *= invMasses[i]; +// dp[i] = -(constraint_jacobian[i]) * (tmp_mat * constraint_value); +// } + +// corr0 = dp[0]; +// corr1 = dp[1]; +// corr2 = dp[2]; +// corr3 = dp[3]; +// corr4 = dp[4]; + +// return true; +// } + +// // ---------------------------------------------------------------------------------------------- +// template +// constexpr bool computeMaterialFrame( +// const VECTOR3d& p0, +// const VECTOR3d& p1, +// const VECTOR3d& p2, +// MATRIX3d& frame) +// { +// frame.col(2) = (p1 - p0); +// frame.col(2).normalize(); + +// frame.col(1) = (frame.col(2).cross(p2 - p0)); +// frame.col(1).normalize(); + +// frame.col(0) = frame.col(1).cross(frame.col(2)); +// return true; +// } + +// // ---------------------------------------------------------------------------------------------- +// template +// constexpr bool computeDarbouxVector(const MATRIX3d& dA, const MATRIX3d& dB, const SCALER mid_edge_length, VECTOR3d& darboux_vector) +// { +// SCALER factor = static_cast(1.0) + dA.col(0).dot(dB.col(0)) + dA.col(1).dot(dB.col(1)) + dA.col(2).dot(dB.col(2)); + +// factor = static_cast(2.0) / (mid_edge_length * factor); + +// for (int c = 0; c < 3; ++c) +// { +// const int i = permutation[c][0]; +// const int j = permutation[c][1]; +// const int k = permutation[c][2]; +// darboux_vector[i] = dA.col(j).dot(dB.col(k)) - dA.col(k).dot(dB.col(j)); +// } +// darboux_vector *= factor; +// return true; +// } + +// // ---------------------------------------------------------------------------------------------- +// template +// constexpr bool computeMaterialFrameDerivative( +// const VECTOR3d& p0, const VECTOR3d& p1, const VECTOR3d& p2, const MATRIX3d& d, +// MATRIX3d& d1p0, MATRIX3d& d1p1, MATRIX3d& d1p2, +// MATRIX3d& d2p0, MATRIX3d& d2p1, MATRIX3d& d2p2, +// MATRIX3d& d3p0, MATRIX3d& d3p1, MATRIX3d& d3p2) +// { +// ////////////////////////////////////////////////////////////////////////// +// // d3pi +// ////////////////////////////////////////////////////////////////////////// +// const VECTOR3d p01 = p1 - p0; +// SCALER length_p01 = p01.norm(); + +// d3p0.col(0) = d.col(2)[0] * d.col(2); +// d3p0.col(1) = d.col(2)[1] * d.col(2); +// d3p0.col(2) = d.col(2)[2] * d.col(2); + +// d3p0.col(0)[0] -= 1.0; +// d3p0.col(1)[1] -= 1.0; +// d3p0.col(2)[2] -= 1.0; + +// d3p0.col(0) *= (static_cast(1.0) / length_p01); +// d3p0.col(1) *= (static_cast(1.0) / length_p01); +// d3p0.col(2) *= (static_cast(1.0) / length_p01); + +// d3p1.col(0) = -d3p0.col(0); +// d3p1.col(1) = -d3p0.col(1); +// d3p1.col(2) = -d3p0.col(2); + +// d3p2.col(0) = VECTOR3d::uniform(0); +// d3p2.col(1) = VECTOR3d::uniform(0); +// d3p2.col(2) = VECTOR3d::uniform(0); + +// ////////////////////////////////////////////////////////////////////////// +// // d2pi +// ////////////////////////////////////////////////////////////////////////// +// const VECTOR3d p02 = p2 - p0; +// const VECTOR3d p01_cross_p02 = p01.cross(p02); + +// const SCALER length_cross = p01_cross_p02.norm(); + +// MATRIX3d mat; +// mat.col(0) = d.col(1)[0] * d.col(1); +// mat.col(1) = d.col(1)[1] * d.col(1); +// mat.col(2) = d.col(1)[2] * d.col(1); + +// mat.col(0)[0] -= 1.0; +// mat.col(1)[1] -= 1.0; +// mat.col(2)[2] -= 1.0; + +// mat.col(0) *= (-static_cast(1.0) / length_cross); +// mat.col(1) *= (-static_cast(1.0) / length_cross); +// mat.col(2) *= (-static_cast(1.0) / length_cross); + +// MATRIX3d product_matrix; +// LSL_GEO::crossProductMatrix(p2 - p1, product_matrix); +// d2p0 = mat * product_matrix; + +// LSL_GEO::crossProductMatrix(p0 - p2, product_matrix); +// d2p1 = mat * product_matrix; + +// LSL_GEO::crossProductMatrix(p1 - p0, product_matrix); +// d2p2 = mat * product_matrix; + +// ////////////////////////////////////////////////////////////////////////// +// // d1pi +// ////////////////////////////////////////////////////////////////////////// +// MATRIX3d product_mat_d3; +// MATRIX3d product_mat_d2; +// LSL_GEO::crossProductMatrix(d.col(2), product_mat_d3); +// LSL_GEO::crossProductMatrix(d.col(1), product_mat_d2); + +// d1p0 = product_mat_d2 * d3p0 - product_mat_d3 * d2p0; +// d1p1 = product_mat_d2 * d3p1 - product_mat_d3 * d2p1; +// d1p2 = -product_mat_d3 * d2p2; +// return true; +// } + +// // ---------------------------------------------------------------------------------------------- +// template +// constexpr bool computeDarbouxGradient( +// const VECTOR3d& darboux_vector, const SCALER length, +// const MATRIX3d& da, const MATRIX3d& db, +// const MATRIX3d dajpi[3][3], const MATRIX3d dbjpi[3][3], +// //const VECTOR3d& bendAndTwistKs, +// MATRIX3d& omega_pa, MATRIX3d& omega_pb, MATRIX3d& omega_pc, MATRIX3d& omega_pd, MATRIX3d& omega_pe +// ) +// { +// SCALER X = static_cast(1.0) + da.col(0).dot(db.col(0)) + da.col(1).dot(db.col(1)) + da.col(2).dot(db.col(2)); +// X = static_cast(2.0) / (length * X); + +// for (int c = 0; c < 3; ++c) +// { +// const int i = permutation[c][0]; +// const int j = permutation[c][1]; +// const int k = permutation[c][2]; +// // pa +// { +// VECTOR3d term1(0,0,0); +// VECTOR3d term2(0,0,0); +// VECTOR3d tmp(0,0,0); + +// // first term +// term1 = dajpi[j][0].transpose() * db.col(k); +// tmp = dajpi[k][0].transpose() * db.col(j); +// term1 = term1 - tmp; +// // second term +// for (int n = 0; n < 3; ++n) +// { +// tmp = dajpi[n][0].transpose() * db.col(n); +// term2 = term2 + tmp; +// } +// omega_pa.col(i) = X * (term1-(0.5 * darboux_vector[i] * length) * term2); +// //omega_pa.col(i) *= bendAndTwistKs[i]; +// } +// // pb +// { +// VECTOR3d term1(0, 0, 0); +// VECTOR3d term2(0, 0, 0); +// VECTOR3d tmp(0, 0, 0); +// // first term +// term1 = dajpi[j][1].transpose() * db.col(k); +// tmp = dajpi[k][1].transpose() * db.col(j); +// term1 = term1 - tmp; +// // third term +// tmp = dbjpi[j][0].transpose() * da.col(k); +// term1 = term1 - tmp; + +// tmp = dbjpi[k][0].transpose() * da.col(j); +// term1 = term1 + tmp; + +// // second term +// for (int n = 0; n < 3; ++n) +// { +// tmp = dajpi[n][1].transpose() * db.col(n); +// term2 = term2 + tmp; + +// tmp = dbjpi[n][0].transpose() * da.col(n); +// term2 = term2 + tmp; +// } +// omega_pb.col(i) = X * (term1-(0.5 * darboux_vector[i] * length) * term2); +// //omega_pb.col(i) *= bendAndTwistKs[i]; +// } +// // pc +// { +// VECTOR3d term1(0, 0, 0); +// VECTOR3d term2(0, 0, 0); +// VECTOR3d tmp(0, 0, 0); + +// // first term +// term1 = dbjpi[j][1].transpose() * da.col(k); +// tmp = dbjpi[k][1].transpose() * da.col(j); +// term1 = term1 - tmp; + +// // second term +// for (int n = 0; n < 3; ++n) +// { +// tmp = dbjpi[n][1].transpose() * da.col(n); +// term2 = term2 + tmp; +// } +// omega_pc.col(i) = -X*(term1+(0.5 * darboux_vector[i] * length) * term2); +// //omega_pc.col(i) *= bendAndTwistKs[i]; +// } +// // pd +// { +// VECTOR3d term1(0, 0, 0); +// VECTOR3d term2(0, 0, 0); +// VECTOR3d tmp(0, 0, 0); +// // first term +// term1 = dajpi[j][2].transpose() * db.col(k); +// tmp = dajpi[k][2].transpose() * db.col(j); +// term1 = term1 - tmp; +// // second term +// for (int n = 0; n < 3; ++n) { +// tmp = dajpi[n][2].transpose() * db.col(n); +// term2 = term2 + tmp; +// } +// omega_pd.col(i) = X*(term1-(0.5 * darboux_vector[i] * length) * term2); +// //omega_pd.col(i) *= bendAndTwistKs[i]; +// } +// // pe +// { +// VECTOR3d term1(0, 0, 0); +// VECTOR3d term2(0, 0, 0); +// VECTOR3d tmp(0, 0, 0); +// // first term +// term1 = dbjpi[j][2].transpose() * da.col(k); +// tmp = dbjpi[k][2].transpose() * da.col(j); +// term1 -= tmp; + +// // second term +// for (int n = 0; n < 3; ++n) +// { +// tmp = dbjpi[n][2].transpose() * da.col(n); +// term2 += tmp; +// } + +// omega_pe.col(i) = -X*(term1+(0.5 * darboux_vector[i] * length) * term2); +// //omega_pe.col(i) *= bendAndTwistKs[i]; +// } +// } +// return true; +// } + }; }; \ No newline at end of file diff --git a/projects/CuLagrange/pbd/constraint_function_kernel/constraint_types.hpp b/projects/CuLagrange/pbd/constraint_function_kernel/constraint_types.hpp new file mode 100644 index 0000000000..17c8c43d40 --- /dev/null +++ b/projects/CuLagrange/pbd/constraint_function_kernel/constraint_types.hpp @@ -0,0 +1,19 @@ +#pragma once + +namespace zeno { namespace PBD_CONSTRAINT { + +constexpr auto CONSTRAINT_KEY = "XPBD_CONSTRAINT"; + +enum category_c : int { + edge_length_constraint, + isometric_bending_constraint, + dihedral_bending_constraint, + p_kp_collision_constraint, + p_p_collision_constraint, + vert_bending_spring, + tri_bending_spring, + bending +}; + +}; +}; \ No newline at end of file diff --git a/projects/CuLagrange/pbd/constraint_function_kernel/generic_constraint.cuh b/projects/CuLagrange/pbd/constraint_function_kernel/generic_constraint.cuh new file mode 100644 index 0000000000..9a590aaab5 --- /dev/null +++ b/projects/CuLagrange/pbd/constraint_function_kernel/generic_constraint.cuh @@ -0,0 +1,8 @@ +#pragma once + +namespace zeno { namespace CONSTRAINT { + + + +}; +}; diff --git a/projects/FBX/MayaCamera.cpp b/projects/FBX/MayaCamera.cpp index d6c1fd1149..8910fc3711 100644 --- a/projects/FBX/MayaCamera.cpp +++ b/projects/FBX/MayaCamera.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -12,9 +13,11 @@ #include #include #include +#include #include "assimp/scene.h" +#include "magic_enum.hpp" #include "Definition.h" #include "json.hpp" @@ -248,15 +251,18 @@ struct LightNode : INode { auto scale = get_input2("scale"); auto rotate = get_input2("rotate"); auto quaternion = get_input2("quaternion"); - auto intensity = get_input2("intensity"); + auto color = get_input2("color"); - std::string shape = "Plane"; + + auto exposure = get_input2("exposure"); + auto intensity = get_input2("intensity"); + intensity *= pow(2.0, exposure); auto prim = std::make_shared(); auto &verts = prim->verts; auto &tris = prim->tris; - if(shape == "Plane"){ + //if(shape == "Plane"){ auto start_point = zeno::vec3f(0.5, 0, 0.5); float rm = 1.0f; float cm = 1.0f; @@ -291,8 +297,7 @@ struct LightNode : INode { // Plane Indices tris.emplace_back(zeno::vec3i(0, 3, 1)); tris.emplace_back(zeno::vec3i(3, 0, 2)); - - } + //} auto &clr = prim->verts.add_attr("clr"); auto c = color * intensity; @@ -309,18 +314,74 @@ struct LightNode : INode { } prim->userData().set2("isRealTimeObject", std::move(isL)); + prim->userData().set2("isL", std::move(isL)); prim->userData().set2("ivD", std::move(inverdir)); prim->userData().set2("pos", std::move(position)); prim->userData().set2("scale", std::move(scale)); prim->userData().set2("rotate", std::move(rotate)); prim->userData().set2("quaternion", std::move(quaternion)); - prim->userData().set2("shape", std::move(shape)); prim->userData().set2("color", std::move(color)); prim->userData().set2("intensity", std::move(intensity)); + auto visible = get_input2("visible"); + auto doubleside = get_input2("doubleside"); + + std::string type = get_input2(lightTypeKey); + auto typeEnum = magic_enum::enum_cast(type).value_or(LightType::Diffuse); + auto typeOrder = magic_enum::enum_integer(typeEnum); + + std::string shape = get_input2(lightShapeKey); + auto shapeEnum = magic_enum::enum_cast(shape).value_or(LightShape::Plane); + auto shapeOrder = magic_enum::enum_integer(shapeEnum); + + auto profile = get_input2("profile"); + + prim->userData().set2("type", std::move(typeOrder)); + prim->userData().set2("shape", std::move(shapeOrder)); + + prim->userData().set2("visible", std::move(visible)); + prim->userData().set2("doubleside", std::move(doubleside)); + prim->userData().set2("lightProfile", std::move(profile)); + set_output("prim", std::move(prim)); } + + const static inline std::string lightShapeKey = "shape"; + + static std::string lightShapeDefaultString() { + auto name = magic_enum::enum_name(LightShape::Plane); + return std::string(name); + } + + static std::string lightShapeListString() { + auto list = magic_enum::enum_names(); + + std::string result; + for (auto& ele : list) { + result += " "; + result += ele; + } + return result; + } + + const static inline std::string lightTypeKey = "type"; + + static std::string lightTypeDefaultString() { + auto name = magic_enum::enum_name(LightType::Diffuse); + return std::string(name); + } + + static std::string lightTypeListString() { + auto list = magic_enum::enum_names(); + + std::string result; + for (auto& ele : list) { + result += " "; + result += ele; + } + return result; + } }; ZENO_DEFNODE(LightNode)({ @@ -330,9 +391,15 @@ ZENO_DEFNODE(LightNode)({ {"vec3f", "rotate", "0, 0, 0"}, {"vec4f", "quaternion", "1, 0, 0, 0"}, {"vec3f", "color", "1, 1, 1"}, + {"float", "exposure", "0"}, {"float", "intensity", "1"}, {"bool", "islight", "1"}, - {"bool", "invertdir", "1"} + {"bool", "invertdir", "1"}, + {"bool", "visible", "0"}, + {"bool", "doubleside", "0"}, + {"string", "profile", ""}, + {"enum " + LightNode::lightShapeListString(), LightNode::lightShapeKey, LightNode::lightShapeDefaultString()}, + {"enum " + LightNode::lightTypeListString(), LightNode::lightTypeKey, LightNode::lightTypeDefaultString()} }, { "prim" diff --git a/zeno/include/zeno/types/LightObject.h b/zeno/include/zeno/types/LightObject.h index 97f3fce8da..d2cc2d245a 100644 --- a/zeno/include/zeno/types/LightObject.h +++ b/zeno/include/zeno/types/LightObject.h @@ -1,10 +1,30 @@ #pragma once +#ifndef __CUDACC_RTC__ + #include #include +#endif + namespace zeno { + enum struct LightType { + Diffuse=0u, Direction=1u, IES=2u + }; + + enum struct LightShape { + Plane=0u, Sphere=1u, Point=2u + }; + + enum LightConfigMask { + LightConfigNull = 0u, + LightConfigVisible = 1u, + LightConfigDoubleside = 2u + }; + +#ifndef __CUDACC_RTC__ + struct LightData { //vec3f pos{1, 1, 0}; vec3f lightDir{normalize(vec3f(1, 1, 0))}; @@ -27,4 +47,5 @@ struct LightObject : IObjectClone, LightData { } }; +#endif } diff --git a/zeno/src/nodes/mtl/ShaderAttrs.cpp b/zeno/src/nodes/mtl/ShaderAttrs.cpp index 4016ace2c4..bb59105d4e 100644 --- a/zeno/src/nodes/mtl/ShaderAttrs.cpp +++ b/zeno/src/nodes/mtl/ShaderAttrs.cpp @@ -33,7 +33,7 @@ struct ShaderInputAttr : ShaderNodeClone { ZENDEFNODE(ShaderInputAttr, { { - {"enum pos clr nrm uv tang bitang NoL LoV N T L V H reflectance fresnel instPos instNrm instUv instClr instTang attrs.localPosLazy() attrs.uniformPosLazy()", "attr", "pos"}, + {"enum pos clr nrm uv tang bitang NoL LoV N T L V H reflectance fresnel instPos instNrm instUv instClr instTang prd.rndf() attrs.localPosLazy() attrs.uniformPosLazy()", "attr", "pos"}, {"enum float vec2 vec3 vec4", "type", "vec3"}, }, { diff --git a/zeno/src/nodes/mtl/ShaderFinalize.cpp b/zeno/src/nodes/mtl/ShaderFinalize.cpp index c32f218526..9dfb48bbe4 100644 --- a/zeno/src/nodes/mtl/ShaderFinalize.cpp +++ b/zeno/src/nodes/mtl/ShaderFinalize.cpp @@ -115,6 +115,13 @@ struct ShaderFinalize : INode { }); auto commonCode = em.getCommonCode(); + auto sssRadiusMethod = get_input2("sssRadius"); + if (sssRadiusMethod == "Fixed") { + commonCode += "#define _SSS_FIXED_RADIUS_ 1 \n"; + } else { + commonCode += "#define _SSS_FIXED_RADIUS_ 0 \n"; + } + auto mtl = std::make_shared(); mtl->frag = std::move(code); @@ -139,6 +146,9 @@ struct ShaderFinalize : INode { int vol_depth = (int)get_input2("vol_depth"); float vol_extinction = get_input2("vol_extinction"); + auto VolumeEmissionScaler = get_input2("VolumeEmissionScaler"); + commonCode += "#define VolumeEmissionScaler VolumeEmissionScalerType::" + VolumeEmissionScaler + "\n"; + vol_depth = clamp(vol_depth, 9, 99); commonCode += "static const int _vol_depth = " + std::to_string(vol_depth) + ";\n"; @@ -226,8 +236,11 @@ ZENDEFNODE(ShaderFinalize, { {"float", "specular", "1.0"}, {"float", "subsurface", "0.0"}, {"float", "thickness", "0.0"}, - {"vec3f", "sssParam", "1,1,1"}, + + {"enum Fixed Adaptive", "sssRadius", "Fixed"}, + {"vec3f", "sssParam", "1.0,1.0,1.0"}, {"vec3f", "sssColor", "1.0,1.0,1.0"}, + {"float", "specularTint", "0.0"}, {"float", "anisotropic", "0.0"}, {"float", "anisoRotation", "0.0"}, @@ -257,6 +270,8 @@ ZENDEFNODE(ShaderFinalize, { {"list", "tex2dList"},//TODO: bate's asset manager {"list", "tex3dList"}, + {"enum Raw Density Absorption", "VolumeEmissionScaler", "Raw"}, + {"float", "vol_depth", "99"}, {"float", "vol_extinction", "1"}, {"vec3f", "vol_sample_albedo", "0.5,0.5,0.5"}, diff --git a/zeno/src/nodes/mtl/ShaderTexture.cpp b/zeno/src/nodes/mtl/ShaderTexture.cpp index 4e5ddcdf80..c6da2af04f 100644 --- a/zeno/src/nodes/mtl/ShaderTexture.cpp +++ b/zeno/src/nodes/mtl/ShaderTexture.cpp @@ -51,7 +51,7 @@ struct ShaderTexture2D : ShaderNodeClone struct ShaderTexture3D : ShaderNodeClone { enum struct SamplingMethod { - Closest, Trilinear, Triquadratic, Tricubic + Closest, Trilinear, Triquadratic, Tricubic, Stochastic }; static std::string methodDefaultString() { diff --git a/zeno/src/nodes/prim/WBErode.cpp b/zeno/src/nodes/prim/WBErode.cpp index 9535ab0499..eded0fc387 100644 --- a/zeno/src/nodes/prim/WBErode.cpp +++ b/zeno/src/nodes/prim/WBErode.cpp @@ -2514,7 +2514,7 @@ struct HF_maskByFeature : INode { // //!useCurvature && // //!useOcclusion) { - mask[idx] = 0; +// mask[idx] = 0; } if (useSlope) { diff --git a/zeno/src/nodes/prim/WBNoise.cpp b/zeno/src/nodes/prim/WBNoise.cpp index 4c3655595e..6885e88392 100644 --- a/zeno/src/nodes/prim/WBNoise.cpp +++ b/zeno/src/nodes/prim/WBNoise.cpp @@ -1136,7 +1136,8 @@ glm::vec3 noise_random3(glm::vec3 p) { float noise_mydistance(glm::vec3 a, glm::vec3 b, int t) { if (t == 0) { - return length(a - b); + float d = length(a - b); + return d*d; } else if (t == 1) { float xx = abs(a.x - b.x); diff --git a/zenovis/src/optx/RenderEngineOptx.cpp b/zenovis/src/optx/RenderEngineOptx.cpp index cb0c4c373f..4289e43874 100644 --- a/zenovis/src/optx/RenderEngineOptx.cpp +++ b/zenovis/src/optx/RenderEngineOptx.cpp @@ -1,3 +1,6 @@ +#include "optixPathTracer.h" +#include "vec_math.h" +#include #ifdef ZENO_ENABLE_OPTIX #include "../../xinxinoptix/xinxinoptixapi.h" #include "../../xinxinoptix/SDK/sutil/sutil.h" @@ -217,12 +220,12 @@ struct GraphicsManager { auto sphere_scale = ud.get2("sphere_scale"); auto uniform_scaling = sphere_scale[0] == sphere_scale[1] && sphere_scale[2] == sphere_scale[0]; - if (uniform_scaling && instanced) { + if (instanced) { auto sphere_center = ud.get2("sphere_center"); auto sphere_radius = ud.get2("sphere_radius"); - sphere_radius *= sphere_scale[0]; + sphere_radius *= fmaxf(fmaxf(sphere_scale[0], sphere_scale[1]), sphere_scale[2]); - xinxinoptix::preload_sphere_crowded(key, mtlid, instID, sphere_radius, sphere_center); + xinxinoptix::preload_sphere_instanced(key, mtlid, instID, sphere_radius, sphere_center); } else { //zeno::vec4f row0, row1, row2, row3; @@ -526,6 +529,14 @@ struct GraphicsManager { clr = zeno::vec3f(30000.0f, 30000.0f, 30000.0f); } + auto type = prim_in->userData().get2("type", 0); + auto shape = prim_in->userData().get2("shape", 0); + + auto visible = prim_in->userData().get2("visible", 0); + auto doubleside = prim_in->userData().get2("doubleside", 0); + auto lightProfilePath = prim_in->userData().get2("lightProfile", ""); + OptixUtil::addTexture(lightProfilePath); + std::cout << "light: p"<userData().get2("ProceduralSky", 0) == 1) { sky_found = true; @@ -766,6 +777,13 @@ struct RenderEngineOptx : RenderEngine, zeno::disable_copy { std::pair shadtpl2; }; + ShaderTemplateInfo _fallback_shader_template { + "DefaultFallback.cu", false, {}, {}, {} + }; + void ensure_fallback() { + _fallback_shader_template.shadtmpl = sutil::lookupIncFile(_fallback_shader_template.name.c_str()); + } + ShaderTemplateInfo _default_shader_template { "DeflMatShader.cu", false, {}, {}, {} }; @@ -774,6 +792,10 @@ struct RenderEngineOptx : RenderEngine, zeno::disable_copy { "volume.cu", false, {}, {}, {} }; + ShaderTemplateInfo _light_shader_template { + "Light.cu", false, {}, {}, {} + }; + std::set cachedMeshesMaterials, cachedSphereMaterials; std::map cachedMeshMatLUT; bool meshMatLUTChanged(std::map& newLUT) { @@ -799,18 +821,6 @@ struct RenderEngineOptx : RenderEngine, zeno::disable_copy { _template.shadtmpl = sutil::lookupIncFile(_template.name.c_str()); - auto marker = std::string("//PLACEHOLDER"); - auto marker_length = marker.length(); - - auto start_marker = _template.shadtmpl.find(marker); - - if (start_marker != std::string::npos) { - auto end_marker = _template.shadtmpl.find(marker, start_marker + marker_length); - - _template.shadtmpl.replace(start_marker, marker_length, "/*PLACEHOLDER"); - _template.shadtmpl.replace(end_marker, marker_length, "PLACEHOLDER*/"); - } - std::string_view tplsv = _template.shadtmpl; std::string_view tmpcommon = "//COMMON_CODE"; auto pcommon = tplsv.find(tmpcommon); @@ -886,51 +896,54 @@ struct RenderEngineOptx : RenderEngine, zeno::disable_copy { } if (sizeNeedUpdate || camNeedUpdate) { - zeno::log_debug("[zeno-optix] updating camera"); - //xinxinoptix::set_show_grid(opt.show_grid); - //xinxinoptix::set_normal_check(opt.normal_check); - //xinxinoptix::set_enable_gi(opt.enable_gi); - //xinxinoptix::set_smooth_shading(opt.smooth_shading); - //xinxinoptix::set_render_wireframe(opt.render_wireframe); - //xinxinoptix::set_background_color(opt.bgcolor.r, opt.bgcolor.g, opt.bgcolor.b); - //xinxinoptix::setDOF(cam.m_dof); - //xinxinoptix::setAperature(cam.m_aperture); - auto lodright = glm::normalize(glm::cross(cam.m_lodfront, cam.m_lodup)); - auto lodup = glm::normalize(glm::cross(lodright, cam.m_lodfront)); - //zeno::log_warn("lodup = {}", zeno::other_to_vec<3>(cam.m_lodup)); - //zeno::log_warn("lodfront = {}", zeno::other_to_vec<3>(cam.m_lodfront)); - //zeno::log_warn("lodright = {}", zeno::other_to_vec<3>(lodright)); - xinxinoptix::set_perspective(glm::value_ptr(lodright), glm::value_ptr(lodup), - glm::value_ptr(cam.m_lodfront), glm::value_ptr(cam.m_lodcenter), - cam.getAspect(), cam.m_fov, cam.focalPlaneDistance, cam.m_aperture); - //xinxinoptix::set_projection(glm::value_ptr(cam.m_proj)); - } - if(lightNeedUpdate){ - //zeno::log_debug("[zeno-optix] updating light"); - xinxinoptix::optixupdatelight(); + zeno::log_debug("[zeno-optix] updating camera"); - lightNeedUpdate = false; + auto lodright = glm::normalize(glm::cross(cam.m_lodfront, cam.m_lodup)); + auto lodup = glm::normalize(glm::cross(lodright, cam.m_lodfront)); + + xinxinoptix::set_perspective(glm::value_ptr(lodright), glm::value_ptr(lodup), + glm::value_ptr(cam.m_lodfront), glm::value_ptr(cam.m_lodcenter), + cam.getAspect(), cam.m_fov, cam.focalPlaneDistance, cam.m_aperture); } if (meshNeedUpdate || matNeedUpdate || staticNeedUpdate) { //zeno::log_debug("[zeno-optix] updating scene"); //zeno::log_debug("[zeno-optix] updating material"); - std::vector _mesh_shader_list{}; - std::vector _sphere_shader_list{}; - std::vector _volume_shader_list{}; + std::vector> _mesh_shader_list{}; + std::vector> _sphere_shader_list{}; + std::vector> _volume_shader_list{}; std::map meshMatLUT{}; std::map matIDtoShaderIndex{}; ensure_shadtmpl(_default_shader_template); ensure_shadtmpl(_volume_shader_template); + ensure_shadtmpl(_light_shader_template); + + auto _default_shader_fallback = std::make_shared(_fallback_shader_template.shadtmpl); + auto _volume_shader_fallback = std::make_shared(_volume_shader_template.shadtmpl); - _mesh_shader_list.push_back({ - ShaderMaker::Mesh, - "Default", - _default_shader_template.shadtmpl, - std::vector() - }); + { + auto tmp = std::make_shared(); + + tmp->mark = ShaderMaker::Mesh; + tmp->matid = "Default"; + tmp->source = _light_shader_template.shadtmpl; + tmp->fallback = std::make_shared(""); + + _mesh_shader_list.push_back(tmp); + } + + { + auto tmp = std::make_shared(); + + tmp->mark = ShaderMaker::Sphere; + tmp->matid = "Default"; + tmp->source = _light_shader_template.shadtmpl; + tmp->fallback = std::make_shared(""); + + _sphere_shader_list.push_back(tmp); + } meshMatLUT.clear(); meshMatLUT.insert({"Default", 0}); @@ -1000,7 +1013,8 @@ struct RenderEngineOptx : RenderEngine, zeno::disable_copy { } } - auto selected_template = has_vdb? _volume_shader_template : _default_shader_template; + const auto& selected_template = has_vdb? _volume_shader_template : _default_shader_template; + const auto& selected_fallback = has_vdb? _volume_shader_fallback : _default_shader_fallback; std::string shader; auto common_code = mtldet->common; @@ -1043,33 +1057,33 @@ struct RenderEngineOptx : RenderEngine, zeno::disable_copy { } ShaderPrepared shaderP; - shaderP.material = mtldet->mtlidkey; + shaderP.matid = mtldet->mtlidkey; shaderP.source = shader; shaderP.tex_names = shaderTex; + shaderP.fallback = selected_fallback; if (has_vdb) { - + shaderP.mark = ShaderMaker::Volume; - _volume_shader_list.push_back(shaderP); + _volume_shader_list.push_back(std::make_shared(shaderP)); } else { if (cachedMeshesMaterials.count(mtldet->mtlidkey) > 0) { - meshMatLUT.insert( - {mtldet->mtlidkey, (int)_mesh_shader_list.size()}); + meshMatLUT.insert({mtldet->mtlidkey, (int)_mesh_shader_list.size()}); - shaderP.mark = ShaderMaker::Mesh; - _mesh_shader_list.push_back(shaderP); + shaderP.mark = ShaderMaker::Mesh; + _mesh_shader_list.push_back(std::make_shared(shaderP)); } if (cachedSphereMaterials.count(mtldet->mtlidkey) > 0) { shaderP.mark = ShaderMaker::Sphere; - _sphere_shader_list.push_back(shaderP); + _sphere_shader_list.push_back(std::make_shared(shaderP)); } } } - std::vector allShaders{}; + std::vector> allShaders{}; allShaders.reserve(_mesh_shader_list.size()+_sphere_shader_list.size()+_volume_shader_list.size()); allShaders.insert(allShaders.end(), _mesh_shader_list.begin(), _mesh_shader_list.end()); @@ -1082,7 +1096,7 @@ struct RenderEngineOptx : RenderEngine, zeno::disable_copy { for (uint i=0; imatid + ":" + std::to_string((ref->mark)); matIDtoShaderIndex[combinedID] = i; } @@ -1093,17 +1107,6 @@ struct RenderEngineOptx : RenderEngine, zeno::disable_copy { xinxinoptix::updateVolume(volume_shader_offset); } - xinxinoptix::foreach_sphere_crowded([&matIDtoShaderIndex, sphere_shader_offset](const std::string &mtlid, std::vector &sbtoffset_list) { - - auto combinedID = mtlid + ":" + std::to_string(ShaderMaker::Sphere); - - if (matIDtoShaderIndex.count(combinedID) > 0) { - auto shaderIndex = matIDtoShaderIndex.at(combinedID); - sbtoffset_list.push_back(shaderIndex - sphere_shader_offset); - } - }); - - xinxinoptix::SpheresCrowded.sbt_count = _sphere_shader_list.size(); OptixUtil::matIDtoShaderIndex = matIDtoShaderIndex; bool bMeshMatLUTChanged = false; //if meshMatLUT need update @@ -1117,34 +1120,44 @@ struct RenderEngineOptx : RenderEngine, zeno::disable_copy { if (meshNeedUpdate || bMeshMatLUTChanged) { + OptixUtil::logInfoVRAM("Before update Mesh"); - OptixUtil::logInfoVRAM("Before update Mesh"); - - if(staticNeedUpdate) + if(staticNeedUpdate) { xinxinoptix::UpdateStaticMesh(meshMatLUT); - + } xinxinoptix::UpdateDynamicMesh(meshMatLUT); - OptixUtil::logInfoVRAM("Before update Inst"); - xinxinoptix::UpdateInst(); - OptixUtil::logInfoVRAM("After update Inst"); + OptixUtil::logInfoVRAM("Before update Inst"); - xinxinoptix::updateInstancedSpheresGAS(); - xinxinoptix::updateCrowdedSpheresGAS(); - xinxinoptix::updateUniformSphereGAS(); + xinxinoptix::UpdateInst(); + OptixUtil::logInfoVRAM("After update Inst"); - OptixUtil::logInfoVRAM("After update Sphere"); + xinxinoptix::updateSphereXAS(); + OptixUtil::logInfoVRAM("After update Sphere"); xinxinoptix::UpdateStaticInstMesh(meshMatLUT); xinxinoptix::UpdateDynamicInstMesh(meshMatLUT); xinxinoptix::CopyInstMeshToGlobalMesh(); - xinxinoptix::UpdateGasAndIas(staticNeedUpdate); + xinxinoptix::UpdateMeshGasAndIas(staticNeedUpdate); + + xinxinoptix::cleanupSpheresCPU(); + + xinxinoptix::optixupdateend(); + std::cout<<"Finish optix update" << std::endl; } - - xinxinoptix::optixupdateend(); - std::cout<<"optix update End\n"; - xinxinoptix::cleanupSpheres(); - std::cout<<"cleanupSpheres\n"; + + } + + if(lightNeedUpdate){ + CppTimer timer; timer.tick(); + xinxinoptix::buildLightTree(); + timer.tock("Build LightTree"); + } + + if (lightNeedUpdate || matNeedUpdate || meshNeedUpdate || staticNeedUpdate) { + + lightNeedUpdate = false; + xinxinoptix::buildRootIAS(); matNeedUpdate = false; meshNeedUpdate = false; diff --git a/zenovis/xinxinoptix/CMakeLists.txt b/zenovis/xinxinoptix/CMakeLists.txt index e29e0a752b..00e2fbd354 100644 --- a/zenovis/xinxinoptix/CMakeLists.txt +++ b/zenovis/xinxinoptix/CMakeLists.txt @@ -5,19 +5,26 @@ target_sources(zenovis PRIVATE optixPathTracer.cpp optixPathTracer.h OptiXStuff.h + Host.h volume/optixVolume.cpp volume/optixVolume.h + optixSphere.cpp optixSphere.h - + Shape.h + XAS.h - ies/ies_loader.cpp - ies/ies_loader.h + LightTree.cpp + LightTree.h + LightBounds.cpp + LightBounds.h + ies/ies.cpp + ies/ies.h SDK/sutil/Aabb.h SDK/sutil/Quaternion.h SDK/sutil/Camera.cpp SDK/sutil/Record.h - SDK/sutil/Camera.h SDK/sutil/Scene.cpp - SDK/sutil/CUDAOutputBuffer.h SDK/sutil/Scene.h + SDK/sutil/Camera.h SDK/cuda/climits.h + SDK/sutil/CUDAOutputBuffer.h SDK/cuda/cstdint.h SDK/sutil/Exception.h SDK/sutil/sutilapi.h SDK/sutil/GLDisplay.cpp SDK/sutil/sutil.cpp SDK/sutil/GLDisplay.h SDK/sutil/sutil.h @@ -86,15 +93,22 @@ set(FILE_LIST # ${CUDA_PATH}/include/@nvfunctional ${CUDA_PATH}/include/@math_constants.h ${CUDA_PATH}/include/@vector_types.h - ${CUDA_PATH}/include/@vector_functions.h + ${CUDA_PATH}/include/@vector_functions.h ${CMAKE_CURRENT_SOURCE_DIR}/SDK/@cuda/random.h ${CMAKE_CURRENT_SOURCE_DIR}/SDK/@cuda/helpers.h + ${CMAKE_CURRENT_SOURCE_DIR}/SDK/@cuda/climits.h + ${CMAKE_CURRENT_SOURCE_DIR}/SDK/@cuda/cstdint.h + ${CMAKE_CURRENT_SOURCE_DIR}/SDK/@sutil/vec_math.h ${CMAKE_CURRENT_SOURCE_DIR}/SDK/@sutil/Preprocessor.h + #include + ${CMAKE_CURRENT_SOURCE_DIR}/../../zeno/include/@zeno/types/LightObject.h + ${CMAKE_CURRENT_SOURCE_DIR}/@optixPathTracer.h ${CMAKE_CURRENT_SOURCE_DIR}/@TraceStuff.h ${CMAKE_CURRENT_SOURCE_DIR}/@PTKernel.cu + ${CMAKE_CURRENT_SOURCE_DIR}/@DefaultFallback.cu ${CMAKE_CURRENT_SOURCE_DIR}/@DeflMatShader.cu ${CMAKE_CURRENT_SOURCE_DIR}/@DisneyBRDF.h ${CMAKE_CURRENT_SOURCE_DIR}/@DisneyBSDF.h @@ -102,9 +116,16 @@ set(FILE_LIST ${CMAKE_CURRENT_SOURCE_DIR}/@IOMat.h ${CMAKE_CURRENT_SOURCE_DIR}/@proceduralSky.h + ${CMAKE_CURRENT_SOURCE_DIR}/@LightBounds.h + ${CMAKE_CURRENT_SOURCE_DIR}/@LightTree.h + + ${CMAKE_CURRENT_SOURCE_DIR}/@Sampling.h + ${CMAKE_CURRENT_SOURCE_DIR}/@Shape.h + ${CMAKE_CURRENT_SOURCE_DIR}/@Light.cu + ${CMAKE_CURRENT_SOURCE_DIR}/@Light.h ${CMAKE_CURRENT_SOURCE_DIR}/@volume.cu ${CMAKE_CURRENT_SOURCE_DIR}/@volume.h - + ${NVDB_PATH}/@nanovdb/NanoVDB.h ${NVDB_PATH}/@nanovdb/util/Ray.h ${NVDB_PATH}/@nanovdb/util/HDDA.h diff --git a/zenovis/xinxinoptix/DefaultFallback.cu b/zenovis/xinxinoptix/DefaultFallback.cu new file mode 100644 index 0000000000..7070aaaeb5 --- /dev/null +++ b/zenovis/xinxinoptix/DefaultFallback.cu @@ -0,0 +1,24 @@ +#include +#include "TraceStuff.h" + +extern "C" __global__ void __anyhit__shadow_cutout() +{ + RadiancePRD* prd = getPRD(); + prd->shadowAttanuation = {}; + prd->attenuation = {}; + optixTerminateRay(); + return; +} + +extern "C" __global__ void __closesthit__radiance() +{ + RadiancePRD* prd = getPRD(); + prd->done = true; + prd->depth += 1; + return; +} + +extern "C" __global__ void __closesthit__occlusion() +{ + setPayloadOcclusion( true ); +} diff --git a/zenovis/xinxinoptix/DeflMatShader.cu b/zenovis/xinxinoptix/DeflMatShader.cu index 808890fe72..4f9787ded1 100644 --- a/zenovis/xinxinoptix/DeflMatShader.cu +++ b/zenovis/xinxinoptix/DeflMatShader.cu @@ -1,19 +1,23 @@ #include #include -#include #include + +#include #include "optixPathTracer.h" + #include "TraceStuff.h" #include "zxxglslvec.h" -#include "DisneyBRDF.h" -#include "DisneyBSDF.h" -#include "proceduralSky.h" + #include "IOMat.h" +#include "Light.h" #define _SPHERE_ 0 #define TRI_PER_MESH 4096 //COMMON_CODE +#include "DisneyBRDF.h" +#include "DisneyBSDF.h" + template static __inline__ __device__ MatOutput evalMat(cudaTextureObject_t zenotex[], float4* uniforms, MatInput const &attrs) { @@ -142,7 +146,7 @@ static __inline__ __device__ bool isBadVector(vec3& vector) { return true; } } - return length(vector) <= 0; + return dot(vector, vector) <= 0; } static __inline__ __device__ bool isBadVector(float3& vector) { @@ -163,32 +167,38 @@ extern "C" __global__ void __anyhit__shadow_cutout() const OptixTraversableHandle gas = optixGetGASTraversableHandle(); const uint sbtGASIndex = optixGetSbtGASIndex(); - const uint prim_idx = optixGetPrimitiveIndex(); + const uint primIdx = optixGetPrimitiveIndex(); - const float3 ray_orig = optixGetWorldRayOrigin(); - const float3 ray_dir = optixGetWorldRayDirection(); + const float3 ray_orig = optixGetWorldRayOrigin(); + const float3 ray_dir = optixGetWorldRayDirection(); + const float3 P = ray_orig + optixGetRayTmax() * ray_dir; HitGroupData* rt_data = (HitGroupData*)optixGetSbtDataPointer(); - const float3 P = ray_orig + optixGetRayTmax() * ray_dir; const auto zenotex = rt_data->textures; - RadiancePRD* prd = getPRD(); + RadiancePRD* prd = getPRD(); MatInput attrs{}; + bool sphere_external_ray = false; + #if (_SPHERE_) float4 q; // sphere center (q.x, q.y, q.z), sphere radius q.w - optixGetSphereData( gas, prim_idx, sbtGASIndex, 0.f, &q ); + optixGetSphereData( gas, primIdx, sbtGASIndex, 0.f, &q ); - float3 _pos_world_ = ray_orig + optixGetRayTmax() * ray_dir; + float3 _pos_world_ = P; float3 _pos_object_ = optixTransformPointFromWorldToObjectSpace( _pos_world_ ); - float3 _normal_object_ = ( _pos_object_ - make_float3( q ) ) / q.w; + float3& _center_object_ = *(float3*)&q; + + float3 _normal_object_ = ( _pos_object_ - _center_object_ ) / q.w; float3 _normal_world_ = normalize( optixTransformNormalFromObjectToWorldSpace( _normal_object_ ) ); - //float3 P = _pos_world_; + auto _origin_object_ = optixGetObjectRayOrigin(); + sphere_external_ray = length(_origin_object_ - _center_object_) > q.w; + float3 N = _normal_world_; N = faceforward( N, -ray_dir, N ); @@ -208,7 +218,7 @@ extern "C" __global__ void __anyhit__shadow_cutout() #else size_t inst_idx2 = optixGetInstanceIndex(); size_t inst_idx = rt_data->meshIdxs[inst_idx2]; - size_t vert_idx_offset = (inst_idx * TRI_PER_MESH + prim_idx)*3; + size_t vert_idx_offset = (inst_idx * TRI_PER_MESH + primIdx)*3; float m16[16]; m16[12]=0; m16[13]=0; m16[14]=0; m16[15]=1; @@ -216,30 +226,25 @@ extern "C" __global__ void __anyhit__shadow_cutout() mat4& meshMat = *reinterpret_cast(&m16); float3 _vertices_[3]; - optixGetTriangleVertexData( gas, - prim_idx, - sbtGASIndex, - 0, - _vertices_); - - float3 av0 = _vertices_[0]; //make_float3(rt_data->vertices[vert_idx_offset + 0]); - float3 av1 = _vertices_[1]; //make_float3(rt_data->vertices[vert_idx_offset + 1]); - float3 av2 = _vertices_[2]; //make_float3(rt_data->vertices[vert_idx_offset + 2]); + optixGetTriangleVertexData( gas, primIdx, sbtGASIndex, 0, _vertices_); + + float3& av0 = _vertices_[0]; //make_float3(rt_data->vertices[vert_idx_offset + 0]); + float3& av1 = _vertices_[1]; //make_float3(rt_data->vertices[vert_idx_offset + 1]); + float3& av2 = _vertices_[2]; //make_float3(rt_data->vertices[vert_idx_offset + 2]); vec4 bv0 = vec4(av0.x, av0.y, av0.z, 1); vec4 bv1 = vec4(av1.x, av1.y, av1.z, 1); vec4 bv2 = vec4(av2.x, av2.y, av2.z, 1); bv0 = meshMat * bv0; bv1 = meshMat * bv1; bv2 = meshMat * bv2; - float3 v0 = make_float3(bv0.x, bv0.y, bv0.z); - float3 v1 = make_float3(bv1.x, bv1.y, bv1.z); - float3 v2 = make_float3(bv2.x, bv2.y, bv2.z); + float3& v0 = *(float3*)&bv0; //make_float3(bv0.x, bv0.y, bv0.z); + float3& v1 = *(float3*)&bv1; //make_float3(bv1.x, bv1.y, bv1.z); + float3& v2 = *(float3*)&bv2; //make_float3(bv2.x, bv2.y, bv2.z); float3 N_0 = normalize( cross( normalize(v1-v0), normalize(v2-v0) ) ); if (isBadVector(N_0)) { - //assert(false); N_0 = DisneyBSDF::SampleScatterDirection(prd->seed); N_0 = faceforward( N_0, -ray_dir, N_0 ); } @@ -300,7 +305,7 @@ extern "C" __global__ void __anyhit__shadow_cutout() attrs.instClr = rt_data->instClr[inst_idx2]; attrs.instTang = rt_data->instTang[inst_idx2]; - unsigned short isLight = rt_data->lightMark[inst_idx * TRI_PER_MESH + prim_idx]; + unsigned short isLight = rt_data->lightMark[inst_idx * TRI_PER_MESH + primIdx]; #endif MatOutput mats = evalMaterial(zenotex, rt_data->uniforms, attrs); @@ -311,6 +316,7 @@ extern "C" __global__ void __anyhit__shadow_cutout() attrs.tang = cross(attrs.nrm, b); N = mats.nrm.x * attrs.tang + mats.nrm.y * b + mats.nrm.z * attrs.nrm; } + //end of material computation //mats.metallic = clamp(mats.metallic,0.01, 0.99); mats.roughness = clamp(mats.roughness, 0.01f,0.99f); @@ -347,26 +353,34 @@ extern "C" __global__ void __anyhit__shadow_cutout() } else { - //roll a dice float p = rnd(prd->seed); - if (p < opacity){ + + float skip = opacity; + #if (_SPHERE_) + if (sphere_external_ray) { + skip *= opacity; + } + #endif + + if (p < skip){ optixIgnoreIntersection(); }else{ + if(length(prd->shadowAttanuation) < 0.01f){ prd->shadowAttanuation = vec3(0.0f); optixTerminateRay(); return; } + if(specTrans==0.0f){ prd->shadowAttanuation = vec3(0.0f); optixTerminateRay(); return; } - //prd->shadowAttanuation = vec3(0,0,0); - //optixTerminateRay(); if(specTrans > 0.0f){ + if(thin == 0.0f && ior>1.0f) { prd->nonThinTransHit++; @@ -376,14 +390,25 @@ extern "C" __global__ void __anyhit__shadow_cutout() prd->shadowAttanuation = vec3(0,0,0); optixTerminateRay(); return; - }else{ - float nDi = fabs(dot(N,ray_dir)); - vec3 tmp = prd->shadowAttanuation; - tmp = tmp * (vec3(1)-BRDFBasics::fresnelSchlick(vec3(1)-basecolor,nDi)); - prd->shadowAttanuation = tmp; + } + float nDi = fabs(dot(N,ray_dir)); + vec3 fakeTrans = vec3(1)-BRDFBasics::fresnelSchlick(vec3(1)-basecolor,nDi); + prd->shadowAttanuation = prd->shadowAttanuation * fakeTrans; + + #if (_SPHERE_) + if (sphere_external_ray) { + prd->shadowAttanuation *= vec3(1, 0, 0); + if (nDi < (1.0f-_FLT_EPL_)) { + prd->shadowAttanuation = {}; + optixTerminateRay(); return; + } else { + prd->shadowAttanuation *= fakeTrans; + } + } + #endif optixIgnoreIntersection(); - } + return; } } @@ -393,25 +418,6 @@ extern "C" __global__ void __anyhit__shadow_cutout() } } -static __inline__ __device__ -int GetLightIndex(float p, ParallelogramLight* lightP, int n) -{ - int s = 0, e = n-1; - while( s < e ) - { - int j = (s+e)/2; - float pc = lightP[j].cdf/lightP[n-1].cdf; - if(pctextures; + MatInput attrs{}; #if (_SPHERE_) @@ -491,15 +462,14 @@ extern "C" __global__ void __closesthit__radiance() float4 q; // sphere center (q.x, q.y, q.z), sphere radius q.w - optixGetSphereData( gas, optixGetPrimitiveIndex(), sbtGASIndex, 0.0f, &q ); + optixGetSphereData( gas, primIdx, sbtGASIndex, 0.0f, &q ); - float3 _pos_world_ = ray_orig + optixGetRayTmax() * ray_dir; + float3 _pos_world_ = P; float3 _pos_object_ = optixTransformPointFromWorldToObjectSpace( _pos_world_ ); float3 _normal_object_ = ( _pos_object_ - make_float3( q ) ) / q.w; float3 _normal_world_ = normalize( optixTransformNormalFromObjectToWorldSpace( _normal_object_ ) ); - float3 P = _pos_world_; float3 N = _normal_world_; prd->geometryNormal = N; @@ -520,7 +490,7 @@ extern "C" __global__ void __closesthit__radiance() size_t inst_idx2 = optixGetInstanceIndex(); size_t inst_idx = rt_data->meshIdxs[inst_idx2]; - size_t vert_idx_offset = (inst_idx * TRI_PER_MESH + prim_idx)*3; + size_t vert_idx_offset = (inst_idx * TRI_PER_MESH + primIdx)*3; float m16[16]; m16[12]=0; m16[13]=0; m16[14]=0; m16[15]=1; @@ -528,24 +498,20 @@ extern "C" __global__ void __closesthit__radiance() mat4& meshMat = *reinterpret_cast(&m16); float3 _vertices_[3]; - optixGetTriangleVertexData( gas, - prim_idx, - sbtGASIndex, - 0, - _vertices_); + optixGetTriangleVertexData( gas, primIdx, sbtGASIndex, 0, _vertices_); - float3 av0 = _vertices_[0]; //make_float3(rt_data->vertices[vert_idx_offset + 0]); - float3 av1 = _vertices_[1]; //make_float3(rt_data->vertices[vert_idx_offset + 1]); - float3 av2 = _vertices_[2]; //make_float3(rt_data->vertices[vert_idx_offset + 2]); + float3& av0 = _vertices_[0]; //make_float3(rt_data->vertices[vert_idx_offset + 0]); + float3& av1 = _vertices_[1]; //make_float3(rt_data->vertices[vert_idx_offset + 1]); + float3& av2 = _vertices_[2]; //make_float3(rt_data->vertices[vert_idx_offset + 2]); vec4 bv0 = vec4(av0.x, av0.y, av0.z, 1); vec4 bv1 = vec4(av1.x, av1.y, av1.z, 1); vec4 bv2 = vec4(av2.x, av2.y, av2.z, 1); bv0 = meshMat * bv0; bv1 = meshMat * bv1; bv2 = meshMat * bv2; - float3 v0 = make_float3(bv0.x, bv0.y, bv0.z); - float3 v1 = make_float3(bv1.x, bv1.y, bv1.z); - float3 v2 = make_float3(bv2.x, bv2.y, bv2.z); + float3& v0 = *(float3*)&bv0; //make_float3(bv0.x, bv0.y, bv0.z); + float3& v1 = *(float3*)&bv1; //make_float3(bv1.x, bv1.y, bv1.z); + float3& v2 = *(float3*)&bv2; //make_float3(bv2.x, bv2.y, bv2.z); float3 N_0 = normalize( cross( normalize(v1-v0), normalize(v2-v1) ) ); // this value has precision issue for big float @@ -557,8 +523,7 @@ extern "C" __global__ void __closesthit__radiance() prd->geometryNormal = N_0; - float3 P = optixGetWorldRayOrigin() + optixGetRayTmax()*ray_dir; - unsigned short isLight = rt_data->lightMark[inst_idx * TRI_PER_MESH + prim_idx]; + unsigned short isLight = rt_data->lightMark[inst_idx * TRI_PER_MESH + primIdx]; //float w = rt_data->vertices[ vert_idx_offset+0 ].w; /* MODMA */ @@ -668,6 +633,8 @@ extern "C" __global__ void __closesthit__radiance() prd->tmp_normal = N; } + bool next_ray_is_going_inside = false; + /* MODME */ auto basecolor = mats.basecolor; auto metallic = mats.metallic; @@ -701,6 +668,9 @@ extern "C" __global__ void __closesthit__radiance() auto sssParam = mats.sssParam; auto scatterStep = mats.scatterStep; + + sssParam = subsurface>0? sssParam*subsurface : sssParam; + subsurface = subsurface>0? 1 : 0; //discard fully opacity pixels //opacity = clamp(opacity, 0.0f, 0.99f); prd->opacity = opacity; @@ -815,7 +785,6 @@ extern "C" __global__ void __closesthit__radiance() prd->done = true; return; } - float is_refl; float3 inDir = ray_dir; @@ -824,7 +793,7 @@ extern "C" __global__ void __closesthit__radiance() float rPdf = 0.0f; float fPdf = 0.0f; float rrPdf = 0.0f; - float ffPdf = 0.0f; + float3 T = attrs.tang; float3 B; if(length(T)>0) @@ -877,7 +846,7 @@ extern "C" __global__ void __closesthit__radiance() prd->geometryNormal, -normalize(ray_dir), thin>0.5f, - prd->next_ray_is_going_inside, + next_ray_is_going_inside, wi, reflectance, rPdf, @@ -906,8 +875,6 @@ extern "C" __global__ void __closesthit__radiance() if(isDiff || prd->diffDepth>0){ prd->diffDepth++; } - - prd->passed = false; bool inToOut = false; @@ -917,7 +884,7 @@ extern "C" __global__ void __closesthit__radiance() //istransmission = (istransmission && thin<0.5 && mats.doubleSide==false); if(istransmission || flag == DisneyBSDF::diracEvent) { //if(flag == DisneyBSDF::transmissionEvent || flag == DisneyBSDF::diracEvent) { - prd->next_ray_is_going_inside = dot(vec3(prd->geometryNormal),vec3(wi))<=0; + next_ray_is_going_inside = dot(vec3(prd->geometryNormal),vec3(wi))<=0; } if(thin>0.5f || mats.doubleSide>0.5f) @@ -925,24 +892,25 @@ extern "C" __global__ void __closesthit__radiance() if (prd->curMatIdx > 0) { vec3 sigma_t, ss_alpha; prd->readMat(sigma_t, ss_alpha); + + vec3 trans; if (ss_alpha.x<0.0f) { // is inside Glass - prd->attenuation *= DisneyBSDF::Transmission(sigma_t, optixGetRayTmax()); - prd->attenuation2 *= DisneyBSDF::Transmission(sigma_t, optixGetRayTmax()); + trans = DisneyBSDF::Transmission(sigma_t, optixGetRayTmax()); } else { - prd->attenuation *= DisneyBSDF::Transmission2(sigma_t * ss_alpha, sigma_t, prd->channelPDF, optixGetRayTmax(), true); - prd->attenuation2 *= DisneyBSDF::Transmission2(sigma_t * ss_alpha, sigma_t, prd->channelPDF, optixGetRayTmax(), true); + trans = DisneyBSDF::Transmission2(sigma_t * ss_alpha, sigma_t, prd->channelPDF, optixGetRayTmax(), true); } - }else { - prd->attenuation *= 1; + prd->attenuation *= trans; + prd->attenuation2 *= trans; } - prd->next_ray_is_going_inside = false; + + next_ray_is_going_inside = false; + }else{ //if(flag == DisneyBSDF::transmissionEvent || flag == DisneyBSDF::diracEvent) { if(istransmission || flag == DisneyBSDF::diracEvent) { - if(prd->next_ray_is_going_inside){ - if(thin < 0.5f && mats.doubleSide < 0.5f ) - { + if(next_ray_is_going_inside){ + outToIn = true; inToOut = false; @@ -963,29 +931,23 @@ extern "C" __global__ void __closesthit__radiance() vec3 channelPDF = vec3(1.0f/3.0f); prd->maxDistance = scatterStep>0.5f? DisneyBSDF::SampleDistance2(prd->seed, extinction, extinction, channelPDF) : 1e16f; prd->pushMat(extinction); + prd->isSS = false; } else { - vec3 channelPDF = vec3(1.0f/3.0f); - prd->maxDistance = DisneyBSDF::SampleDistance2(prd->seed, vec3(prd->attenuation) * prd->ss_alpha, prd->sigma_t, channelPDF); + prd->maxDistance = DisneyBSDF::SampleDistance2(prd->seed, vec3(prd->attenuation) * prd->ss_alpha, prd->sigma_t, prd->channelPDF); //here is the place caused inf ray:fixed auto min_sg = fmax(fmin(fmin(prd->sigma_t.x, prd->sigma_t.y), prd->sigma_t.z), 1e-8f); //what should be the right value??? //prd->maxDistance = max(prd->maxDistance, 10/min_sg); //printf("maxdist:%f\n",prd->maxDistance); - prd->channelPDF = channelPDF; - // already calculated in BxDF - - // if (idx.x == w/2 && idx.y == h/2) { - // printf("into sss, sigma_t, alpha: %f, %f, %f\n", prd->sigma_t.x, prd->sigma_t.y, prd->sigma_t.z,prd->ss_alpha.x, prd->ss_alpha.y, prd->ss_alpha.z); - // } + // already calculated in BxDF prd->pushMat(prd->sigma_t, prd->ss_alpha); + prd->isSS = true; } prd->scatterDistance = scatterDistance; prd->scatterStep = scatterStep; - } - } else{ outToIn = false; @@ -999,38 +961,28 @@ extern "C" __global__ void __closesthit__radiance() trans = vec3(1.0f); } else if (ss_alpha.x<0.0f) { // Glass - trans = DisneyBSDF::Transmission(sigma_t, optixGetRayTmax()); } else { trans = DisneyBSDF::Transmission2(sigma_t * ss_alpha, sigma_t, prd->channelPDF, optixGetRayTmax(), true); } - prd->attenuation2 *= trans; prd->attenuation *= trans; - + prd->attenuation2 *= trans; + prd->popMat(sigma_t, ss_alpha); prd->medium = (prd->curMatIdx==0)? DisneyBSDF::PhaseFunctions::vacuum : DisneyBSDF::PhaseFunctions::isotropic; - if(ss_alpha.x >= 0.0f) //next ray in 3s object - { - prd->isSS = true; - prd->maxDistance = DisneyBSDF::SampleDistance2(prd->seed, vec3(prd->attenuation) * ss_alpha, sigma_t, prd->channelPDF); - } - else + if(ss_alpha.x < 0.0f) { prd->isSS = false; prd->maxDistance = 1e16; } - - // if (prd->medium != DisneyBSDF::PhaseFunctions::vacuum) { - - // prd->bad = true; - - // printf("%f %f %f %f %f %f %f %f \n matIdx = %d isotropic = %d \n", prd->sigma_t_queue[0].x, prd->sigma_t_queue[1].x, prd->sigma_t_queue[2].x, prd->sigma_t_queue[3].x, prd->sigma_t_queue[4].x, prd->sigma_t_queue[5].x, prd->sigma_t_queue[6].x, prd->sigma_t_queue[7].x, - // prd->curMatIdx, prd->medium); - // printf("matIdx = %d isotropic = %d \n\n", prd->curMatIdx, prd->medium); - // } + else //next ray in 3s object + { + prd->isSS = true; + prd->maxDistance = DisneyBSDF::SampleDistance2(prd->seed, vec3(prd->attenuation) * ss_alpha, sigma_t, prd->channelPDF); + } } }else{ if(prd->medium == DisneyBSDF::PhaseFunctions::isotropic){ @@ -1042,13 +994,12 @@ extern "C" __global__ void __closesthit__radiance() { prd->maxDistance = 1e16f; } - else if (prd->ss_alpha.x<0.0f) { // Glass + else if (ss_alpha.x<0.0f) { // Glass trans = DisneyBSDF::Transmission(sigma_t, optixGetRayTmax()); vec3 channelPDF = vec3(1.0f/3.0f); prd->maxDistance = scatterStep>0.5f? DisneyBSDF::SampleDistance2(prd->seed, sigma_t, sigma_t, channelPDF) : 1e16f; } else { // SSS trans = DisneyBSDF::Transmission2(sigma_t * ss_alpha, sigma_t, prd->channelPDF, optixGetRayTmax(), true); - prd->channelPDF = vec3(1.0f/3.0f); prd->maxDistance = DisneyBSDF::SampleDistance2(prd->seed, vec3(prd->attenuation) * ss_alpha, sigma_t, prd->channelPDF); prd->isSS = true; } @@ -1056,16 +1007,17 @@ extern "C" __global__ void __closesthit__radiance() prd->attenuation2 *= trans; prd->attenuation *= trans; } - else - { - prd->isSS = false; - prd->medium = DisneyBSDF::PhaseFunctions::vacuum; - prd->channelPDF = vec3(1.0f/3.0f); - prd->maxDistance = 1e16f; - } + else + { + prd->isSS = false; + prd->medium = DisneyBSDF::PhaseFunctions::vacuum; + prd->channelPDF = vec3(1.0f/3.0f); + prd->maxDistance = 1e16f; + } } } - prd->medium = prd->next_ray_is_going_inside?DisneyBSDF::PhaseFunctions::isotropic : prd->curMatIdx==0?DisneyBSDF::PhaseFunctions::vacuum : DisneyBSDF::PhaseFunctions::isotropic; + + prd->medium = next_ray_is_going_inside?DisneyBSDF::PhaseFunctions::isotropic : prd->curMatIdx==0?DisneyBSDF::PhaseFunctions::vacuum : DisneyBSDF::PhaseFunctions::isotropic; if(thin>0.5f){ vec3 H = normalize(vec3(normalize(wi)) + vec3(-normalize(ray_dir))); @@ -1084,184 +1036,70 @@ extern "C" __global__ void __closesthit__radiance() prd->attenuation *= reflectance; prd->depth++; - auto P_OLD = P; - P = rtgems::offset_ray(P, prd->geometryNormal); - + auto shadingP = rtgems::offset_ray(P, prd->geometryNormal); prd->radiance = make_float3(0.0f,0.0f,0.0f); - float3 light_attenuation = make_float3(1.0f,1.0f,1.0f); - float pl = rnd(prd->seed); - int lidx = GetLightIndex(pl, params.lights, params.num_lights); - float sum = 0.0f; - for(int lidx=0;lidxdepth>=3) roughness = clamp(roughness, 0.5f,0.99f); - RadiancePRD shadow_prd {}; - shadow_prd.seed = prd->seed; - shadow_prd.shadowAttanuation = make_float3(1.0f, 1.0f, 1.0f); - shadow_prd.nonThinTransHit = (thin == false && specTrans > 0) ? 1 : 0; + vec3 rd, rs, rt; // captured by lambda + + auto evalBxDF = [&](const float3& _wi_, const float3& _wo_, float& thisPDF, vec3 illum = vec3(1.0f)) -> float3 { + + const auto& L = _wi_; // pre-normalized + const vec3& V = _wo_; // pre-normalized + + float3 lbrdf = DisneyBSDF::EvaluateDisney2(illum, + basecolor, sssColor, metallic, subsurface, specular, max(prd->minSpecRough,roughness), specularTint, anisotropic, anisoRotation, sheen, sheenTint, + clearcoat, clearcoatGloss, ccRough, ccIor, specTrans, scatterDistance, ior, flatness, L, V, T, B, N,prd->geometryNormal, + thin > 0.5f, flag == DisneyBSDF::transmissionEvent ? inToOut : next_ray_is_going_inside, thisPDF, rrPdf, + dot(N, L), rd, rs, rt); - if(rnd(prd->seed)<=0.5f) { - bool computed = false; - float ppl = 0; - for (int lidx = 0; lidx < params.num_lights && computed == false; lidx++) { - ParallelogramLight light = params.lights[lidx]; - float2 z = {rnd(prd->seed), rnd(prd->seed)}; - const float z1 = z.x; - const float z2 = z.y; - float3 light_tpos = light.corner + light.v1 * 0.5f + light.v2 * 0.5f; - float3 light_pos = light.corner + light.v1 * z1 + light.v2 * z2; - - // Calculate properties of light sample (for area based pdf) - float tLdist = length(light_tpos - P); - float3 tL = normalize(light_tpos - P); - float tnDl = 1.0f; //clamp(dot(N, tL), 0.0f, 1.0f); - float tLnDl = clamp(-dot(light.normal, tL), 0.000001f, 1.0f); - float tA = length(cross(params.lights[lidx].v1, params.lights[lidx].v2)); - ppl += length(light.emission) * tnDl * tLnDl * tA / (M_PIf * tLdist * tLdist) / sum; - if (ppl > pl) { - float Ldist = length(light_pos - P) + 1e-6f; - float3 L = normalize(light_pos - P); - float nDl = 1.0f; //clamp(dot(N, L), 0.0f, 1.0f); - float LnDl = clamp(-dot(light.normal, L), 0.0f, 1.0f); - float A = length(cross(params.lights[lidx].v1, params.lights[lidx].v2)); - float weight = 0.0f; - if (nDl > 0.0f && LnDl > 0.0f) { - - traceOcclusion(params.handle, P, L, - 1e-5f, // tmin - Ldist - 1e-5f, // tmax, - &shadow_prd); - - light_attenuation = shadow_prd.shadowAttanuation; - if (fmaxf(light_attenuation) > 0.0f) { - - weight = sum * nDl / tnDl * LnDl / tLnDl * (tLdist * tLdist) / (Ldist * Ldist) / - (length(light.emission)+1e-6f) ; - } - } - prd->LP = P; - prd->Ldir = L; - prd->nonThinTransHit = (thin == false && specTrans > 0) ? 1 : 0; - prd->Lweight = weight; - vec3 rd, rs, rt; - float3 lbrdf = DisneyBSDF::EvaluateDisney2(vec3(1.0f), - basecolor, sssColor, metallic, subsurface, specular, max(prd->minSpecRough,roughness), specularTint, anisotropic, anisoRotation, sheen, sheenTint, - clearcoat, clearcoatGloss, ccRough, ccIor, specTrans, scatterDistance, ior, flatness, L, -normalize(inDir), T, B, N,prd->geometryNormal, - thin > 0.5f, flag == DisneyBSDF::transmissionEvent ? inToOut : prd->next_ray_is_going_inside, ffPdf, rrPdf, - dot(N, L), rd, rs, rt); - MatOutput mat2; - if(thin>0.5f){ - vec3 H = normalize(vec3(normalize(L)) + vec3(-normalize(inDir))); - attrs.N = N; - attrs.T = cross(B,N); - attrs.L = vec3(normalize(L)); - attrs.V = vec3(-normalize(inDir)); - attrs.H = normalize(H); - attrs.reflectance = lbrdf; - attrs.fresnel = DisneyBSDF::DisneyFresnel( basecolor, metallic, ior, specularTint, dot(attrs.H, attrs.V), dot(attrs.H, attrs.L), false); - mat2 = evalReflectance(zenotex, rt_data->uniforms, attrs); - } - prd->radiance = light_attenuation * weight * 2.0f * light.emission * (thin>0.5f? float3(mat2.reflectance):lbrdf); - computed = true; - } - } - } else { - float env_weight_sum = 1e-8f; - int NSamples = prd->depth<=2?1:1;//16 / pow(4.0f, (float)prd->depth-1); - for(int samples=0;samplesseed); - //vec3 sunLightDir = vec3(params.sunLightDirX, params.sunLightDirY, params.sunLightDirZ); - int hasenv = params.skynx * params.skyny; - hasenv = params.usingHdrSky? hasenv : 0; - float envpdf = 1; - float3 illum = make_float3(0,0,0); - vec3 sunLightDir = hasenv? ImportanceSampleEnv(params.skycdf, params.sky_start, - params.skynx, params.skyny, p, envpdf) - : vec3(params.sunLightDirX, params.sunLightDirY, params.sunLightDirZ); - auto sun_dir = BRDFBasics::halfPlaneSample(prd->seed, sunLightDir, - params.sunSoftness * 0.0f); //perturb the sun to have some softness - sun_dir = hasenv ? normalize(sunLightDir):normalize(sun_dir); - float tmpPdf; - illum = float3(envSky(sun_dir, sunLightDir, make_float3(0., 0., 1.), - 40, // be careful - .45, 15., 1.030725f * 0.3f, params.elapsedTime, tmpPdf)); - - auto LP = P; - auto Ldir = sun_dir; - - rtgems::offset_ray(LP, sun_dir); - traceOcclusion(params.handle, LP, sun_dir, - 1e-5f, // tmin - 1e16f, // tmax, - &shadow_prd); - vec3 rd, rs, rt; - lbrdf = DisneyBSDF::EvaluateDisney2(vec3(illum), - basecolor, sssColor, metallic, subsurface, specular, roughness, specularTint, anisotropic, - anisoRotation, sheen, sheenTint, clearcoat, clearcoatGloss, ccRough, ccIor, specTrans, scatterDistance, - ior, flatness, sun_dir, -normalize(inDir), T, B, N, prd->geometryNormal,thin > 0.5f, - flag == DisneyBSDF::transmissionEvent ? inToOut : prd->next_ray_is_going_inside, ffPdf, rrPdf, - dot(N, float3(sun_dir)), rd, rs, rt); - light_attenuation = shadow_prd.shadowAttanuation; - //if (fmaxf(light_attenuation) > 0.0f) { - // auto sky = float3(envSky(sun_dir, sunLightDir, make_float3(0., 0., 1.), - // 10, // be careful - // .45, 15., 1.030725 * 0.3, params.elapsedTime)); MatOutput mat2; - if (thin > 0.5f) { - vec3 H = normalize(vec3(normalize(sun_dir)) + vec3(-normalize(inDir))); + if(thin>0.5f){ + vec3 H = normalize(vec3(normalize(L)) + V); attrs.N = N; - attrs.T = cross(B, N); - attrs.L = vec3(normalize(sun_dir)); - attrs.V = vec3(-normalize(inDir)); + attrs.T = cross(B,N); + attrs.L = vec3(normalize(L)); + attrs.V = V; attrs.H = normalize(H); attrs.reflectance = lbrdf; - attrs.fresnel = DisneyBSDF::DisneyFresnel(basecolor, metallic, ior, specularTint, dot(attrs.H, attrs.V), - dot(attrs.H, attrs.L), false); + attrs.fresnel = DisneyBSDF::DisneyFresnel( basecolor, metallic, ior, specularTint, dot(attrs.H, attrs.V), dot(attrs.H, attrs.L), false); mat2 = evalReflectance(zenotex, rt_data->uniforms, attrs); } - float misWeight = BRDFBasics::PowerHeuristic(tmpPdf, ffPdf); - misWeight = misWeight>0.0f?misWeight:1.0f; - misWeight = ffPdf>1e-5f?misWeight:0.0f; - misWeight = tmpPdf>1e-5?misWeight:0.0f; - prd->radiance += misWeight * 1.0f / (float)NSamples * - light_attenuation / tmpPdf * 2.0f * (thin > 0.5f ? float3(mat2.reflectance) : lbrdf); - prd->radiance_d = rd * vec3(misWeight * 1.0f / (float)NSamples * - light_attenuation / tmpPdf * 2.0f); - prd->radiance_s = rs * vec3(misWeight * 1.0f / (float)NSamples * - light_attenuation / tmpPdf * 2.0f); - prd->radiance_t = rt * vec3(misWeight * 1.0f / (float)NSamples * - light_attenuation / tmpPdf * 2.0f); - } - //prd->radiance = float3(clamp(vec3(prd->radiance), vec3(0.0f), vec3(100.0f))); - } - P = P_OLD; + return (thin>0.5f? float3(mat2.reflectance):lbrdf); + }; + + auto taskAux = [&](const vec3& weight) { + prd->radiance_d = rd * weight; + prd->radiance_s = rs * weight; + prd->radiance_t = rt * weight; + }; + + RadiancePRD shadow_prd {}; + shadow_prd.seed = prd->seed; + shadow_prd.shadowAttanuation = make_float3(1.0f, 1.0f, 1.0f); + shadow_prd.nonThinTransHit = (thin == false && specTrans > 0) ? 1 : 0; + prd->direction = normalize(wi); + + DirectLighting(prd, shadow_prd, shadingP, ray_dir, evalBxDF, &taskAux); + if(thin<0.5f && mats.doubleSide<0.5f){ - prd->origin = rtgems::offset_ray(P, (prd->next_ray_is_going_inside)? -prd->geometryNormal : prd->geometryNormal); + prd->origin = rtgems::offset_ray(P, (next_ray_is_going_inside)? -prd->geometryNormal : prd->geometryNormal); } else { - prd->origin = rtgems::offset_ray(P, ( dot(prd->direction, prd->geometryNormal) <0 )? -prd->geometryNormal : prd->geometryNormal); + prd->origin = rtgems::offset_ray(P, ( dot(prd->direction, prd->geometryNormal) < 0 )? -prd->geometryNormal : prd->geometryNormal); + } + + if (prd->medium != DisneyBSDF::vacuum) { + prd->_mask_ = (uint8_t)(EverythingMask ^ VolumeMatMask); + } else { + prd->_mask_ = EverythingMask; } - prd->radiance += float3(mats.emission); - prd->CH = 1.0; + prd->radiance += mats.emission; } extern "C" __global__ void __closesthit__occlusion() diff --git a/zenovis/xinxinoptix/DisneyBRDF.h b/zenovis/xinxinoptix/DisneyBRDF.h index 173292120c..fd202a095b 100644 --- a/zenovis/xinxinoptix/DisneyBRDF.h +++ b/zenovis/xinxinoptix/DisneyBRDF.h @@ -8,7 +8,7 @@ static __inline__ __device__ float PowerHeuristic(float a, float b) { float t = a * a; - return t / (b * b + t); + return t / (b * b + t + 1e-6); } static __inline__ __device__ float fresnel(float cosT){ float v = clamp(1-cosT,0.0f,1.0f); diff --git a/zenovis/xinxinoptix/DisneyBSDF.h b/zenovis/xinxinoptix/DisneyBSDF.h index 203e9a46c0..045299e573 100644 --- a/zenovis/xinxinoptix/DisneyBSDF.h +++ b/zenovis/xinxinoptix/DisneyBSDF.h @@ -4,8 +4,6 @@ #include "DisneyBRDF.h" - - //list of component: //Sheen //Clearcoat @@ -80,9 +78,13 @@ namespace DisneyBSDF{ return xmid; } + static __inline__ __device__ void setup_subsurface_radius(float eta, vec3 albedo, vec3 &radius) { + #if _SSS_FIXED_RADIUS_ + radius = radius * 0.25f / M_PIf; + #else float inv_eta = 1.0f/eta; float F_dr = inv_eta * (-1.440f * inv_eta + 0.710f) + 0.668f + 0.0636f * eta; float fourthirdA = (4.0f / 3.0f) * (1.0f + F_dr) / @@ -92,7 +94,7 @@ namespace DisneyBSDF{ alpha_prime.y = bssrdf_dipole_compute_alpha_prime(albedo.y, fourthirdA); alpha_prime.z = bssrdf_dipole_compute_alpha_prime(albedo.z, fourthirdA); radius = radius * sqrt(3.0f * abs(vec3(1.0) - alpha_prime)); - + #endif } static __inline__ __device__ void subsurface_random_walk_remap(const float albedo, @@ -143,14 +145,16 @@ namespace DisneyBSDF{ } static __inline__ __device__ - void CalculateExtinction2(vec3 albedo, vec3 radius, vec3 &sigma_t, vec3 &alpha) + void CalculateExtinction2(vec3 albedo, vec3 radius, vec3 &sigma_t, vec3 &alpha, float eta) { vec3 r = radius; - setup_subsurface_radius(3.0, albedo, r); + setup_subsurface_radius(eta, albedo, r); subsurface_random_walk_remap(albedo.x, r.x, 0, sigma_t.x, alpha.x); subsurface_random_walk_remap(albedo.y, r.y, 0, sigma_t.y, alpha.y); subsurface_random_walk_remap(albedo.z, r.z, 0, sigma_t.z, alpha.z); //sigma_s = sigma_t * alpha; + + //printf("radius= %f %f %f, \nr= %f %f %f \n", radius.x, radius.y, radius.z, r.x, r.y, r.z); } static __inline__ __device__ @@ -332,9 +336,9 @@ namespace DisneyBSDF{ float glassWt = (1.0 - metallic) * specTrans; float schlickWt = BRDFBasics::SchlickWeight(abs(dot(wo, wm))); - float psss = subsurface/(1.0f + subsurface); + float psss = subsurface; //event probability - float diffPr = dielectricWt * (1.0f - psss); + float diffPr = dielectricWt; float sssPr = dielectricWt * psss; float dielectricPr = dielectricWt * Luminance(mix(Cspec0, vec3(1.0), schlickWt)); float metalPr = metalWt * Luminance(mix(baseColor, vec3(1.0), schlickWt)); @@ -465,8 +469,9 @@ namespace DisneyBSDF{ float FL = BRDFBasics::SchlickWeight(abs(wi.z)); float FV = BRDFBasics::SchlickWeight(abs(wo.z)); float term = wo.z>0?FV:FL; - float tmpPdf = trans?0.5/M_PIf:0.0f; - vec3 d = 1.0f/M_PIf * (1.0f - 0.5f * term) * (trans?vec3(1.0f):vec3(0.0f)) * dielectricWt * subsurface; + float tmpPdf = trans? 1.0f : 0.0f;//0.5/M_PIf:0.0f; + // vec3 d = 1.0f/M_PIf * (1.0f - 0.5f * term) * (trans?vec3(1.0f):vec3(0.0f)) * dielectricWt * subsurface; + vec3 d = (trans?vec3(1.0f):vec3(0.0f)) * dielectricWt * subsurface; dterm = dterm + d; f = f + d; fPdf += tmpPdf * sssPr; @@ -622,7 +627,7 @@ namespace DisneyBSDF{ float F0; BRDFBasics::TintColors(mix(baseColor, sssColor, subsurface), eta, specularTint, sheenTint, F0, Csheen, Cspec0); - Cspec0 = Cspec0 * specular; + Cspec0 = Cspec0; //material layer mix weight float dielectricWt = (1.0 - metallic) * (1.0 - specTrans); @@ -638,11 +643,11 @@ namespace DisneyBSDF{ float hov = mix(hov1, hov2, c); float schlickWt = BRDFBasics::SchlickWeight(hov); - float psss = subsurface/(1.0f + subsurface); + float psss = subsurface; //dielectricWt *= 1.0f - psub; //event probability - float diffPr = dielectricWt * (1.0f - psss); + float diffPr = dielectricWt ; float sssPr = dielectricWt * psss; float dielectricPr = dielectricWt * Luminance(mix(Cspec0, vec3(1.0), schlickWt)); float metalPr = metalWt * Luminance(mix(baseColor, vec3(1.0), schlickWt)); @@ -693,15 +698,14 @@ namespace DisneyBSDF{ wi = -BRDFBasics::UniformSampleHemisphere(r1, r2); isSS = true; flag = transmissionEvent; - vec3 color = mix(baseColor, sssColor, subsurface) * psss; + vec3 color = mix(baseColor, sssColor, subsurface); color = clamp(color, vec3(0.05), vec3(0.99)); vec3 sssRadius = transmiianceColor * subsurface; RadiancePRD *prd = getPRD(); prd->ss_alpha = color; if (isSS) { medium = PhaseFunctions::isotropic; - CalculateExtinction2(color, sssRadius, prd->sigma_t, - prd->ss_alpha); + CalculateExtinction2(color, sssRadius, prd->sigma_t, prd->ss_alpha, 1.4f); } } } diff --git a/zenovis/xinxinoptix/Host.h b/zenovis/xinxinoptix/Host.h new file mode 100644 index 0000000000..fbd30a0005 --- /dev/null +++ b/zenovis/xinxinoptix/Host.h @@ -0,0 +1,43 @@ +#pragma once +#ifndef HOSTED +#define HOSTED + +#ifndef __device__ +#define __device__ /* device */ +#endif + +#ifndef __inline__ +#define __inline__ /* inline */ +#endif + +#ifndef __forceinline__ +#define __forceinline__ __inline__ +#endif + +#include +#include +#include + +#ifndef __CUDACC_RTC__ + +// static inline bool isnan(float f) { +// return f == INFINITY; +// } + +template +static inline OutType bitConvert(InType inValue) { + OutType* outP = (OutType*)&inValue; + OutType outV = *outP; + return outV; +} + +static inline int __float_as_int(float f) { + return bitConvert(f); +} + +static inline float __int_as_float(int i) { + return bitConvert(i);; +} + +#endif // __CUDACC_RTC__ +#endif // HOSTED \ No newline at end of file diff --git a/zenovis/xinxinoptix/Light.cu b/zenovis/xinxinoptix/Light.cu new file mode 100644 index 0000000000..4e1b542789 --- /dev/null +++ b/zenovis/xinxinoptix/Light.cu @@ -0,0 +1,230 @@ +#include +#include +#include + +#include "optixPathTracer.h" +#include "TraceStuff.h" +#include "zeno/types/LightObject.h" +#include "zxxglslvec.h" +#include "DisneyBRDF.h" +#include "DisneyBSDF.h" + +#include "Shape.h" +#include "Light.h" +#include "Sampling.h" +#include "LightTree.h" + +//COMMON_CODE + +static __inline__ __device__ void evalSurface(float4* uniforms) { + + //GENERATED_BEGIN_MARK + + //GENERATED_END_MARK +} + +static __inline__ __device__ float3 sphereUV(float3 &direction) { + + return float3 { + atan2(direction.x, direction.z) / (2.0f*M_PIf) + 0.5f, + direction.y * 0.5f + 0.5f, 0.0f + }; +} + +static __inline__ __device__ bool checkLightGAS(uint instanceId) { + return ( instanceId >= OPTIX_DEVICE_PROPERTY_LIMIT_MAX_INSTANCE_ID-1 ); +} + +extern "C" __global__ void __closesthit__radiance() +{ + RadiancePRD* prd = getPRD(); + if(prd->test_distance) + { + prd->vol_t1 = optixGetRayTmax(); + prd->test_distance = false; return; + } + + const OptixTraversableHandle gas = optixGetGASTraversableHandle(); + const uint sbtGASIndex = optixGetSbtGASIndex(); + const uint primitiveIndex = optixGetPrimitiveIndex(); + + const float3 ray_orig = optixGetWorldRayOrigin(); + const float3 ray_dir = optixGetWorldRayDirection(); + const float3 P = ray_orig + optixGetRayTmax() * ray_dir; + + // HitGroupData* rt_data = (HitGroupData*)optixGetSbtDataPointer(); + // auto zenotex = rt_data->textures; + + auto instanceId = optixGetInstanceId(); + auto isLightGAS = checkLightGAS(instanceId); + + if (params.num_lights == 0 || !isLightGAS) { + prd->depth += 1; + prd->done = true; + return; + } + + uint light_index = 0; + vec3 light_normal {}; + + bool ignore = false; + const auto pType = optixGetPrimitiveType(); + + if (pType == OptixPrimitiveType::OPTIX_PRIMITIVE_TYPE_SPHERE) { + + ignore = params.firstSphereLightIdx == UINT_MAX; + light_index = primitiveIndex + params.firstSphereLightIdx; + } else { + + ignore = params.firstRectLightIdx == UINT_MAX; + auto rect_idx = primitiveIndex / 2; + light_index = rect_idx + params.firstRectLightIdx; + } + + if (ignore) { + prd->depth += 1; + prd->done = true; + return; + } + + light_index = min(light_index, params.num_lights - 1); + auto& light = params.lights[light_index]; + + if (pType == OptixPrimitiveType::OPTIX_PRIMITIVE_TYPE_SPHERE) { + light_normal = normalize(light.sphere.center - ray_orig); + } else { + light_normal = light.N; + } + + auto visible = (light.config & zeno::LightConfigVisible); + + if (!visible && prd->depth == 0) { + auto pos = P; + prd->geometryNormal = light_normal; + prd->offsetUpdateRay(pos, ray_dir); + return; + } + + prd->depth += 1; + prd->done = true; + + float3 lightDirection = optixGetWorldRayDirection(); //light_pos - P; + float lightDistance = optixGetRayTmax(); //length(lightDirection); + + LightSampleRecord lsr; + float3 emission = light.emission; + + if (light.type != zeno::LightType::Diffuse) { + // auto pos = ray_orig + ray_dir * optixGetRayTmax(); + // prd->geometryNormal = normalize(light.sphere.center - ray_orig); + // prd->offsetUpdateRay(pos, ray_dir); + return; + } else { + if (light.shape == zeno::LightShape::Plane) { + light.rect.EvalAfterHit(&lsr, lightDirection, lightDistance, prd->origin); + } else if (light.shape == zeno::LightShape::Sphere) { + light.sphere.EvalAfterHit(&lsr, lightDirection, lightDistance, prd->origin); + } else { + return; + } + } + + if (light.config & zeno::LightConfigDoubleside) { + lsr.NoL = abs(lsr.NoL); + } + + const float _SKY_PROB_ = params.skyLightProbablity(); + + if (lsr.NoL > _FLT_EPL_) { + + auto lightTree = reinterpret_cast(params.lightTreeSampler); + + auto PMF = lightTree->PMF(reinterpret_cast(ray_orig), + reinterpret_cast(prd->geometryNormal), light_index); + + auto lightPickPDF = (1.0f - _SKY_PROB_) * PMF; + DCHECK(lightPickPDF > 0.0f && lightPickPDF < 1.0f); + + if (1 == prd->depth) { + if (light.config & zeno::LightConfigVisible) { + prd->radiance = emission; + } + prd->attenuation = vec3(1.0f); + prd->attenuation2 = vec3(1.0f); + return; + } + + float lightPDF = lightPickPDF * lsr.PDF; + float scatterPDF = prd->samplePdf; //BxDF PDF from previous hit + float misWeight = BRDFBasics::PowerHeuristic(scatterPDF, lightPDF); + + prd->radiance = light.emission * misWeight; + // if (scatterPDF > __FLT_DENORM_MIN__) { + // prd->radiance /= scatterPDF; + // } + } + return; +} + +extern "C" __global__ void __anyhit__shadow_cutout() +{ + const OptixTraversableHandle gas = optixGetGASTraversableHandle(); + const uint sbtGASIndex = optixGetSbtGASIndex(); + const uint primitiveIdx = optixGetPrimitiveIndex(); + + // const float3 ray_orig = optixGetWorldRayOrigin(); + // const float3 ray_dir = optixGetWorldRayDirection(); + // const float3 P = ray_orig + optixGetRayTmax() * ray_dir; + + auto instanceId = optixGetInstanceId(); + auto isLightGAS = checkLightGAS(instanceId); + + RadiancePRD* prd = getPRD(); + + if (params.num_lights == 0 || !isLightGAS) { + optixIgnoreIntersection(); + return; + } + + uint light_index = 0; + vec3 light_normal {}; + + bool ignore = false; + const auto pType = optixGetPrimitiveType(); + + if (pType == OptixPrimitiveType::OPTIX_PRIMITIVE_TYPE_SPHERE) { + + ignore = params.firstSphereLightIdx == UINT_MAX; + light_index = primitiveIdx + params.firstSphereLightIdx; + } else { + + ignore = params.firstRectLightIdx == UINT_MAX; + auto rect_idx = primitiveIdx / 2; + light_index = rect_idx + params.firstRectLightIdx; + } + + if (ignore) { + optixIgnoreIntersection(); + return; + } + + light_index = min(light_index, params.num_lights - 1); + auto& light = params.lights[light_index]; + + bool visible = (light.config & zeno::LightConfigVisible); + + if (visible) { + prd->shadowAttanuation = {}; + prd->attenuation2 = {}; + prd->attenuation = {}; + optixTerminateRay(); + } + + optixIgnoreIntersection(); + return; +} + +extern "C" __global__ void __closesthit__occlusion() +{ + setPayloadOcclusion( true ); +} \ No newline at end of file diff --git a/zenovis/xinxinoptix/Light.h b/zenovis/xinxinoptix/Light.h new file mode 100644 index 0000000000..3f22a211f8 --- /dev/null +++ b/zenovis/xinxinoptix/Light.h @@ -0,0 +1,338 @@ +#pragma once +#include "Sampling.h" +#include "LightTree.h" + +#include "TraceStuff.h" +#include "DisneyBRDF.h" +// #include "DisneyBSDF.h" +#include "proceduralSky.h" + +// static __inline__ __device__ +// int GetLightIndex(float p, GenericLight* lightP, int n) +// { +// int s = 0, e = n-1; +// while( s < e ) +// { +// int j = (s+e)/2; +// float pc = lightP[j].CDF/lightP[n-1].CDF; +// if(pc h_angle_max || h_angle < h_angle_min) { return 0.0f; } + + auto v_angle_min = v_angles[0]; + auto v_angle_max = v_angles[v_num-1]; + + if (v_angle > v_angle_max || v_angle < v_angle_min) { return 0.0f; } + + auto lambda = [](float angle, const float* angles, uint num) -> uint { + + auto start = 0u, end = num-1u; + auto _idx_ = start; + + while (start angle) { + end = _idx_; continue; + } + + if(angles[_idx_+1] < angle) { + start = _idx_+1; continue; + } + + break; + } + return _idx_; + }; + + auto v_idx = lambda(v_angle, v_angles, v_num); + auto h_idx = lambda(h_angle, h_angles, h_num); + + auto _a_ = intensity[h_idx * v_num + v_idx]; + auto _b_ = intensity[h_idx * v_num + v_idx+1]; + + auto _c_ = intensity[(h_idx+1) * v_num + v_idx]; + auto _d_ = intensity[(h_idx+1) * v_num + v_idx+1]; + + auto v_ratio = (v_angle-v_angles[v_idx]) / (v_angles[v_idx+1]-v_angles[v_idx]); + auto h_ratio = (h_angle-h_angles[h_idx]) / (h_angles[h_idx+1]-h_angles[h_idx]); + + auto _ab_ = mix(_a_, _b_, v_ratio); + auto _cd_ = mix(_c_, _d_, v_ratio); + + return mix(_ab_, _cd_, h_ratio); +} + +static __inline__ __device__ void sampleSphereIES(LightSampleRecord& lsr, const float2& uu, const float3& shadingP, const float3& center, float radius) { + + float3 vector = center - shadingP; + float dist2 = dot(vector, vector); + + if (dist2 < radius * radius) { + lsr.PDF = 0.0f; + return; + } + + lsr.dist = sqrtf(dist2); + lsr.dir = vector/lsr.dist; + lsr.n = -lsr.dir; + + lsr.p = center; + if (radius > 0) { + lsr.p += radius * lsr.n; + lsr.p = rtgems::offset_ray(lsr.p, lsr.n); + lsr.dist = length(lsr.p - shadingP); + } + + lsr.NoL = 1.0f; + lsr.PDF = 1.0f; + + lsr.intensity = 1.0f / dist2; +} + +namespace detail { + template struct is_void { + static constexpr bool value = false; + }; + template <> struct is_void { + static constexpr bool value = true; + }; +} + +template +static __forceinline__ __device__ +void DirectLighting(RadiancePRD *prd, RadiancePRD& shadow_prd, const float3& shadingP, const float3& ray_dir, TypeEvalBxDF& evalBxDF, TypeAux* taskAux=nullptr) { + + const float3 wo = normalize(-ray_dir); + float3 light_attenuation = vec3(1.0f); + + const float _SKY_PROB_ = params.skyLightProbablity(); + + float scatterPDF = 1.f; + float UF = prd->rndf(); + + if(UF >= _SKY_PROB_) { + + if (params.num_lights == 0u || params.lightTreeSampler == 0u) return; + + auto lightTree = reinterpret_cast(params.lightTreeSampler); + if (lightTree == nullptr) return; + + float lightPickProb = 1.0f - _SKY_PROB_; + UF = (UF - _SKY_PROB_) / lightPickProb; + + const Vector3f& SP = reinterpret_cast(shadingP); + const Vector3f& SN = reinterpret_cast(prd->geometryNormal); + + auto pick = lightTree->sample(UF, SP, SN); + if (pick.prob <= 0.0f) { return; } + + uint lighIdx = min(pick.lightIdx, params.num_lights-1); + auto& light = params.lights[lighIdx]; + + lightPickProb *= pick.prob; + + LightSampleRecord lsr{}; + float3 emission = light.emission; + + const float* iesProfile = reinterpret_cast(light.ies); + + if (light.type == zeno::LightType::IES && nullptr != iesProfile) { + + auto radius = (light.shape == zeno::LightShape::Sphere)? light.sphere.radius : 0.0f; + + sampleSphereIES(lsr, {}, shadingP, light.cone.p, radius); + if (lsr.PDF <= 0.0f) return; + + auto v_angle = acos(dot(-lsr.dir, light.N)); + auto h_angle = acos(dot(-lsr.dir, light.T)); + + auto intensity = sampleIES(iesProfile, h_angle, v_angle); + if (intensity <= 0.0f) return; + + emission *= intensity; + + } else if (light.type == zeno::LightType::Direction) { + + bool valid = false; + switch (light.shape) { + case zeno::LightShape::Plane: + valid = light.rect.hitAsLight(&lsr, shadingP, -light.N); break; + case zeno::LightShape::Sphere: + valid = light.sphere.hitAsLight(&lsr, shadingP, -light.N); break; + default: return; + } + if (!valid) { return; } + + lsr.intensity = 1.0f; + lsr.PDF = 1.0f; + lsr.NoL = 1.0f; + + } else { // Diffuse + + float2 uu = {prd->rndf(), prd->rndf()}; + + switch (light.shape) { + case zeno::LightShape::Plane: + light.rect.SampleAsLight(&lsr, uu, shadingP); break; + case zeno::LightShape::Sphere: + light.sphere.SampleAsLight(&lsr, uu, shadingP); break; + case zeno::LightShape::Point: + light.point.SampleAsLight(&lsr, uu, shadingP); break; + default: break; + } + } + + lsr.PDF *= lightPickProb; + + if (light.config & zeno::LightConfigDoubleside) { + lsr.NoL = abs(lsr.NoL); + } + + if (lsr.NoL > _FLT_EPL_ && lsr.PDF > _FLT_EPL_) { + + traceOcclusion(params.handle, shadingP, lsr.dir, 0, lsr.dist, &shadow_prd); + + light_attenuation = shadow_prd.shadowAttanuation; + + if (lengthSquared(light_attenuation) > 0.0f) { + + auto bxdf_value = evalBxDF(lsr.dir, wo, scatterPDF); + auto misWeight = 1.0f; + + if (!light.isDeltaLight() && !lsr.isDelta) { + misWeight = BRDFBasics::PowerHeuristic(lsr.PDF, scatterPDF); + } + + emission *= lsr.intensity; + + prd->radiance = light_attenuation * emission * bxdf_value; + prd->radiance *= misWeight / lsr.PDF; + } + } + + } else { + + float env_weight_sum = 1e-8f; + int NSamples = prd->depth<=2?1:1;//16 / pow(4.0f, (float)prd->depth-1); + for(int samples=0;samplesseed), envpdf) + : vec3(params.sunLightDirX, params.sunLightDirY, params.sunLightDirZ); + auto sun_dir = BRDFBasics::halfPlaneSample(prd->seed, sunLightDir, + params.sunSoftness * 0.0f); //perturb the sun to have some softness + sun_dir = hasenv ? normalize(sunLightDir):normalize(sun_dir); + + float tmpPdf; + auto illum = float3(envSky(sun_dir, sunLightDir, make_float3(0., 0., 1.), + 40, // be careful + .45, 15., 1.030725f * 0.3f, params.elapsedTime, tmpPdf)); + if(tmpPdf <= 0.0f) { return; } + + auto LP = shadingP; + auto Ldir = sun_dir; + + if (envpdf < __FLT_DENORM_MIN__) { + return; + } + + //LP = rtgems::offset_ray(LP, sun_dir); + traceOcclusion(params.handle, LP, sun_dir, + 1e-5f, // tmin + 1e16f, // tmax, + &shadow_prd); + + light_attenuation = shadow_prd.shadowAttanuation; + + auto inverseProb = 1.0f/_SKY_PROB_; + auto bxdf_value = evalBxDF(sun_dir, wo, scatterPDF, illum); + + vec3 tmp(1.0f); + + if constexpr(_MIS_) { + float misWeight = BRDFBasics::PowerHeuristic(tmpPdf, scatterPDF); + misWeight = misWeight>0.0f?misWeight:1.0f; + misWeight = scatterPDF>1e-5f?misWeight:0.0f; + misWeight = tmpPdf>1e-5f?misWeight:0.0f; + + tmp = (1.0f / NSamples) * misWeight * inverseProb * light_attenuation / tmpPdf; + } else { + tmp = (1.0f / NSamples) * inverseProb * light_attenuation / tmpPdf; + } + + prd->radiance += (float3)(tmp) * bxdf_value; + + if constexpr (!detail::is_void::value) { + if (taskAux != nullptr) { + (*taskAux)(tmp); + } + }// TypeAux + } + } +}; \ No newline at end of file diff --git a/zenovis/xinxinoptix/LightBounds.cpp b/zenovis/xinxinoptix/LightBounds.cpp new file mode 100644 index 0000000000..018c99c74f --- /dev/null +++ b/zenovis/xinxinoptix/LightBounds.cpp @@ -0,0 +1,61 @@ +#include "LightBounds.h" +#include "Sampling.h" +#include "vec_math.h" + +namespace pbrt { + +float LightBounds::importance(Vector3f p, Vector3f n) const { + // Return importance for light bounds at reference point + // Compute clamped squared distance to reference point + Vector3f pc = (bounds.pMin + bounds.pMax) / 2; + float d2 = lengthSquared(p - pc); + d2 = std::max(d2, length(bounds.diagonal()) / 2); + + // Define cosine and sine clamped subtraction lambdas + auto cosSubClamped = [](float sinTheta_a, float cosTheta_a, float sinTheta_b, float cosTheta_b) -> float { + if (cosTheta_a > cosTheta_b) + return 1; + return cosTheta_a * cosTheta_b + sinTheta_a * sinTheta_b; + }; + + auto sinSubClamped = [](float sinTheta_a, float cosTheta_a, float sinTheta_b, float cosTheta_b) -> float { + if (cosTheta_a > cosTheta_b) + return 0; + return sinTheta_a * cosTheta_b - cosTheta_a * sinTheta_b; + }; + + // Compute sine and cosine of angle to vector _w_, $\theta_\roman{w}$ + Vector3f wi = normalize(p - pc); + float cosTheta_w = dot(Vector3f(w), wi); + if (doubleSided) + cosTheta_w = std::abs(cosTheta_w); + float sinTheta_w = SafeSqrt(1 - Sqr(cosTheta_w)); + + // Compute $\cos\,\theta_\roman{\+b}$ for reference point + float cosTheta_b = BoundSubtendedDirections(bounds, p).cosTheta; + float sinTheta_b = SafeSqrt(1 - Sqr(cosTheta_b)); + + // Compute $\cos\,\theta'$ and test against $\cos\,\theta_\roman{e}$ + float sinTheta_o = SafeSqrt(1 - Sqr(cosTheta_o)); + float cosTheta_x = cosSubClamped(sinTheta_w, cosTheta_w, sinTheta_o, cosTheta_o); + float sinTheta_x = sinSubClamped(sinTheta_w, cosTheta_w, sinTheta_o, cosTheta_o); + float cosThetap = cosSubClamped(sinTheta_x, cosTheta_x, sinTheta_b, cosTheta_b); + if (cosThetap <= cosTheta_e) + return 0; + + // Return final importance at reference point + float importance = phi * cosThetap / d2; + DCHECK(importance >= -1e-3); + // Account for $\cos\theta_\roman{i}$ in importance at surfaces + if (n[0]!=0 && n[1]!=0 && n[2]!=0) { + float cosTheta_i = AbsDot(wi, n); + float sinTheta_i = SafeSqrt(1 - Sqr(cosTheta_i)); + float cosThetap_i = cosSubClamped(sinTheta_i, cosTheta_i, sinTheta_b, cosTheta_b); + importance *= cosThetap_i; + } + + importance = fmaxf(importance, 0.0f); + return importance; +} + +} \ No newline at end of file diff --git a/zenovis/xinxinoptix/LightBounds.h b/zenovis/xinxinoptix/LightBounds.h new file mode 100644 index 0000000000..e6d67cc06e --- /dev/null +++ b/zenovis/xinxinoptix/LightBounds.h @@ -0,0 +1,276 @@ +#pragma once + +#include + +#ifndef __CUDACC_RTC__ + #include + + #include + #include + #include +#endif + +#ifndef INFINITY +#define INFINITY CUDART_INF_F +#endif + +#ifndef FLT_MAX +#define FLT_MAX __FLT_MAX__ +#endif + +#ifdef __CUDACC_RTC__ + +namespace zeno { + + inline Vector3f min(Vector3f a, Vector3f b) { + return fminf(a, b); + } + + inline Vector3f max(Vector3f a, Vector3f b) { + return fmaxf(a, b); + } +} + +#endif + +namespace pbrt { + +struct Bounds3f { + +#ifndef __CUDACC_RTC__ + using Vec3 = zeno::vec<3, float>; +#else + using Vec3 = vec3; +#endif + + Vec3 pMin = Vec3 {FLT_MAX, FLT_MAX, FLT_MAX}; + Vec3 pMax = -Vec3 {FLT_MAX, FLT_MAX, FLT_MAX}; + + Bounds3f() = default; + // Bounds3f(Vec3 v) : pMin(v), pMax(v) {} + // Bounds3f(Vec3 a, Vec3 b) { + + // Vector3f x, y; + + // for (int i=0; i<3; ++i) { + // x[i] = fminf(a[i], b[i]); + // y[i] = fmaxf(a[i], b[i]); + // } + + // pMin = x; + // pMax = y; + // } + + Vec3 operator[](int i) const { + DCHECK(i == 0 || i == 1); + return (i == 0) ? pMin : pMax; + } + + Vec3 &operator[](int i) { + DCHECK(i == 0 || i == 1); + return (i == 0) ? pMin : pMax; + } + + Vec3 diagonal() const { + return pMax - pMin; + } + + Vec3 center() const { + return (pMin + pMax) / 2; + } + + Vec3 offset(Vec3 p) const { + Vector3f _o_ = p - pMin; + _o_ = _o_ / diagonal(); + return _o_; + } + + float area() const { + auto d = diagonal(); + return 2.0f * (d[0] * d[1] + d[0] * d[2] + d[1] * d[2]); + } + + float volume() const { + auto d = diagonal(); + return d[0] * d[1] * d[2]; + } + + int maxDimension() const { + auto d = diagonal(); + if (d[0] > d[1] && d[0] > d[2]) + return 0; + else if (d[1] > d[2]) + return 1; + else + return 2; + } + + bool inside(const Vec3& point) const { + + for (uint32_t i=0; i<3; ++i) { + if (point[i] < pMin[i] || point[i] > pMax[i]) + return false; + } + return true; + } + + void BoundingSphere(Vec3 *center, float *radius) const { + *center = (pMin + pMax) / 2; + *radius = inside(*center) ? distance(*center, pMax) : 0; + } + + bool IsEmpty() const { + return pMin[0] >= pMax[0] || pMin[1] >= pMax[1] || pMin[2] >= pMax[2]; + } + + bool IsDegenerate() const { + return pMin[0] > pMax[0] || pMin[1] > pMax[1] || pMin[2] > pMax[2]; + } +}; + +inline float MaxComponentValue(const Vector3f vvv) { + return fmaxf(fmaxf(vvv[0], vvv[1]), vvv[2]); +} + +static Bounds3f Union(const Bounds3f &a, const Bounds3f &b) { + + Bounds3f result; + + result.pMin = zeno::min(a.pMin, b.pMin); + result.pMax = zeno::max(a.pMax, b.pMax); + + return result; +} + +static Bounds3f Union(const Bounds3f &a, const Vector3f &b) { + + Bounds3f result; + + result.pMin = zeno::min(a.pMin, b); + result.pMax = zeno::max(a.pMax, b); + + return result; +} + +static Bounds3f Union(const Vector3f &b, const Bounds3f &a) { + return Union(a, b); +} + +struct DirectionCone { + + Vector3f w; + float cosTheta = INFINITY; + + DirectionCone() = default; + + explicit DirectionCone(Vector3f w) : DirectionCone(w, 1) {} + + DirectionCone(Vector3f w, float cosTheta) : w(normalize(w)), cosTheta(cosTheta) {} + + bool IsEmpty() const { return cosTheta == INFINITY; } + + static DirectionCone EntireSphere() { return DirectionCone(Vector3f(0, 0, 1), -1); } +}; + +// LightBounds Definition +struct LightBounds { + + Bounds3f bounds; Vector3f w{}; + + float cosTheta_o{}, cosTheta_e{}; + float phi = 0.0f; bool doubleSided = false; + + LightBounds() = default; + LightBounds(const Bounds3f &b, Vector3f w, float phi, float cosTheta_o, float cosTheta_e, bool doubleSided) { + this->bounds = b; + this->w = normalize(w); this->phi = phi; + this->cosTheta_o = cosTheta_o; + this->cosTheta_e = cosTheta_e; + this->doubleSided = doubleSided; + } + + Vector3f centroid() const { return (bounds.pMin + bounds.pMax) / 2.0f; } + + float importance(Vector3f p, Vector3f n) const; +}; + +inline DirectionCone BoundSubtendedDirections(const Bounds3f &b, Vector3f p) { + // Compute bounding sphere for _b_ and check if _p_ is inside + float radius; Vector3f pCenter; + b.BoundingSphere(&pCenter, &radius); + + float lenSquared = lengthSquared(pCenter - p); + + if (lenSquared < Sqr(radius)) + return DirectionCone::EntireSphere(); + + // Compute and return _DirectionCone_ for bounding sphere + Vector3f w = normalize(pCenter - p); + float sin2ThetaMax = Sqr(radius) / lenSquared; + float cosThetaMax = SafeSqrt(1 - sin2ThetaMax); + return DirectionCone(w, cosThetaMax); +} + +#ifndef __CUDACC_RTC__ + +inline void Inverse(DirectionCone& dc) { + dc.w *= -1.0f; +} + +// DirectionCone Function Definitions +static DirectionCone Union(const DirectionCone &a, const DirectionCone &b) { + // Handle the cases where one or both cones are empty + if (a.IsEmpty()) + return b; + if (b.IsEmpty()) + return a; + + // Handle the cases where one cone is inside the other + float theta_a = SafeACos(a.cosTheta); + float theta_b = SafeACos(b.cosTheta); + float theta_d = AngleBetween(a.w, b.w); + if (fminf(theta_d + theta_b, M_PIf) <= theta_a) + return a; + if (fminf(theta_d + theta_a, M_PIf) <= theta_b) + return b; + + // Compute the spread angle of the merged cone, $\theta_o$ + float theta_o = (theta_a + theta_d + theta_b) / 2.0f; + if (theta_o >= M_PIf) + return DirectionCone::EntireSphere(); + + // Find the merged cone's axis and return cone union + float theta_r = theta_o - theta_a; + Vector3f wr = cross(a.w, b.w); + + if (lengthSquared(wr) == 0) + return DirectionCone::EntireSphere(); + //Vector3f w = Rotate(Degrees(theta_r), wr)(a.w); + + glm::mat4 rotate = glm::rotate(Degrees(theta_r), *(glm::vec3*)wr.data()); + glm::vec4 tmp = glm::vec4(a.w[0], a.w[1], a.w[2], 0.0f); + tmp = rotate * tmp; + + Vector3f w {tmp.x, tmp.y, tmp.z}; + return DirectionCone(w, cosf(theta_o)); +} + +inline void Inverse(LightBounds& lb) { + lb.w *= -1.0f; +} + +inline LightBounds Union(const LightBounds& a, const LightBounds& b) { + if (a.phi <= 0) return b; + if (b.phi <= 0) return a; + + DirectionCone cone = Union(DirectionCone(a.w, a.cosTheta_o), DirectionCone(b.w, b.cosTheta_o)); + float cosTheta_o = cone.cosTheta; + float cosTheta_e = fminf(a.cosTheta_e, b.cosTheta_e); + + return LightBounds(Union(a.bounds, b.bounds), cone.w, a.phi + b.phi, cosTheta_o, + cosTheta_e, a.doubleSided | b.doubleSided); +} + +#endif + +} // namespace \ No newline at end of file diff --git a/zenovis/xinxinoptix/LightTree.cpp b/zenovis/xinxinoptix/LightTree.cpp new file mode 100644 index 0000000000..f4d99ef417 --- /dev/null +++ b/zenovis/xinxinoptix/LightTree.cpp @@ -0,0 +1,138 @@ +#include "LightTree.h" +#include "Sampling.h" +#include "optixPathTracer.h" + +#include + +namespace pbrt { +// BVHLightSampler Method Definitions +LightTreeSampler::LightTreeSampler(std::vector &lights) { + + lightBitTrails.resize(lights.size(), 0u); + nodes.reserve(lights.size()); + + std::vector> bvhLights{}; + bvhLights.reserve(lights.size() * 2); + + for (size_t i = 0; i < lights.size(); ++i) { + + auto& light = lights[i]; + LightBounds lightBounds = light.bounds(); + + if (lightBounds.phi > 0) { + bvhLights.push_back(std::make_pair(i, lightBounds)); + rootBounds = Union(rootBounds, lightBounds.bounds); + } + } + if (!bvhLights.empty()) + buildTree(bvhLights, 0, bvhLights.size(), 0, 0); +} + +std::pair LightTreeSampler::buildTree( + std::vector> &bvhLights, + int start, int end, uint32_t bitTrail, int depth) { + + DCHECK(start < end); + // Initialize leaf node if only a single light remains + if (end - start == 1) { + int nodeIndex = nodes.size(); + CompactLightBounds cb(bvhLights[start].second, rootBounds); + int lightIndex = bvhLights[start].first; + nodes.push_back(LightTreeNode::MakeLeaf(lightIndex, cb)); + + lightBitTrails.at(lightIndex) = bitTrail; + return {nodeIndex, bvhLights[start].second}; + } + + // Choose split dimension and position using modified SAH + // Compute bounds and centroid bounds for lights + Bounds3f bounds, centroidBounds; + for (int i = start; i < end; ++i) { + const LightBounds &lb = bvhLights[i].second; + bounds = Union(bounds, lb.bounds); + centroidBounds = Union(centroidBounds, lb.centroid()); + } + + float minCost = INFINITY; + int minCostSplitBucket = -1, minCostSplitDim = -1; + constexpr int nBuckets = 12; + for (int dim = 0; dim < 3; ++dim) { + // Compute minimum cost bucket for splitting along dimension _dim_ + if (centroidBounds.pMax[dim] == centroidBounds.pMin[dim]) + continue; + // Compute _LightBounds_ for each bucket + LightBounds bucketLightBounds[nBuckets]; + for (int i = start; i < end; ++i) { + Vector3f pc = bvhLights[i].second.centroid(); + int b = nBuckets * centroidBounds.offset(pc)[dim]; + if (b == nBuckets) + b = nBuckets - 1; + DCHECK(b >= 0); + DCHECK(b < nBuckets); + bucketLightBounds[b] = Union(bucketLightBounds[b], bvhLights[i].second); + } + + // Compute costs for splitting lights after each bucket + float cost[nBuckets - 1]{}; + for (int i = 0; i < (nBuckets - 1); ++i) { + // Find _LightBounds_ for lights below and above bucket split + LightBounds b0, b1; + for (int j = 0; j <= i; ++j) + b0 = Union(b0, bucketLightBounds[j]); + for (int j = (i + 1); j < nBuckets; ++j) + b1 = Union(b1, bucketLightBounds[j]); + + // Compute final light split cost for bucket + cost[i] = EvaluateCost(b0, bounds, dim) + EvaluateCost(b1, bounds, dim); + } + + // Find light split that minimizes SAH metric + for (int i = 1; i < (nBuckets - 1); ++i) { + if (cost[i] > 0 && cost[i] < minCost) { + minCost = cost[i]; + minCostSplitBucket = i; + minCostSplitDim = dim; + } + } + } + + // Partition lights according to chosen split + int mid; + if (minCostSplitDim == -1) + mid = (start + end) / 2; + else { + const auto *pmid = std::partition( + &bvhLights[start], &bvhLights[end - 1] + 1, + [=](const std::pair &l) { + int b = nBuckets * + centroidBounds.offset(l.second.centroid())[minCostSplitDim]; + if (b == nBuckets) + b = nBuckets - 1; + DCHECK(b >= 0); + DCHECK(b < nBuckets); + return b <= minCostSplitBucket; + }); + mid = pmid - &bvhLights[0]; + if (mid == start || mid == end) + mid = (start + end) / 2; + DCHECK(mid > start && mid < end); + } + + // Allocate interior _LightBVHNode_ and recursively initialize children + int nodeIndex = nodes.size(); + nodes.push_back(LightTreeNode()); + DCHECK(depth < 64); + std::pair child0 = + buildTree(bvhLights, start, mid, bitTrail, depth + 1); + DCHECK(nodeIndex + 1 == child0.first); + std::pair child1 = + buildTree(bvhLights, mid, end, bitTrail | (1u << depth), depth + 1); + + // Initialize interior node and return node index and bounds + LightBounds lb = Union(child0.second, child1.second); + CompactLightBounds cb(lb, rootBounds); + nodes[nodeIndex] = LightTreeNode::MakeInterior(child1.first, cb); + return {nodeIndex, lb}; +} + +} \ No newline at end of file diff --git a/zenovis/xinxinoptix/LightTree.h b/zenovis/xinxinoptix/LightTree.h new file mode 100644 index 0000000000..e2f1dd7d9d --- /dev/null +++ b/zenovis/xinxinoptix/LightTree.h @@ -0,0 +1,379 @@ +#pragma once + +#include "LightBounds.h" +#include "optixPathTracer.h" + +#ifndef __CUDACC_RTC__ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#endif + +namespace pbrt { + +// OctahedralVector Definition +struct OctahedralVector { + public: + // OctahedralVector Public Methods + OctahedralVector() = default; + + OctahedralVector(Vector3f vvv) { + + auto& v = reinterpret_cast(vvv); + + v /= fabsf(v.x) + fabsf(v.y) + fabsf(v.z); + if (v.z >= 0) { + x = Encode(v.x); + y = Encode(v.y); + } else { + // Encode octahedral vector with $z < 0$ + x = Encode((1 - fabsf(v.y)) * Sign(v.x)); + y = Encode((1 - fabsf(v.x)) * Sign(v.y)); + } + } + + explicit operator Vector3f() const { + float3 v; + v.x = -1 + 2 * (x / 65535.f); + v.y = -1 + 2 * (y / 65535.f); + v.z = 1 - (fabsf(v.x) + fabsf(v.y)); + // Reparameterize directions in the $z<0$ portion of the octahedron + if (v.z < 0) { + float xo = v.x; + v.x = (1 - fabsf(v.y)) * Sign(xo); + v.y = (1 - fabsf(xo)) * Sign(v.y); + } + + return normalize(reinterpret_cast(v)); + } + + private: + // OctahedralVector Private Methods + static float Sign(float v) { return copysignf(1.f, v); } + + static uint16_t Encode(float f) { + return roundf(clamp((f + 1) / 2.0f, 0.0f, 1.0f) * 65535.f); + } + + // OctahedralVector Private Members + uint16_t x, y; +}; + +// CompactLightBounds Definition +struct CompactLightBounds { + public: + // CompactLightBounds Public Methods + CompactLightBounds() = default; + + CompactLightBounds(const LightBounds &lb, const Bounds3f &allb) : w(normalize(lb.w)), phi(lb.phi) + { + this->meta = { + QuantizeCos(lb.cosTheta_o), + QuantizeCos(lb.cosTheta_e), + lb.doubleSided + }; + // Quantize bounding box into _qb_ + for (int c = 0; c < 3; ++c) { + qb[0][c] = + floorf(QuantizeBounds(lb.bounds[0][c], allb.pMin[c], allb.pMax[c])); + qb[1][c] = + ceilf(QuantizeBounds(lb.bounds[1][c], allb.pMin[c], allb.pMax[c])); + } + } + + bool isDoubleSided() const { return meta.doubleSided; } + + float CosTheta_o() const { return 2 * (meta.qCosTheta_o / 32767.f) - 1; } + float CosTheta_e() const { return 2 * (meta.qCosTheta_e / 32767.f) - 1; } + + inline float lerp(float t, const float a, const float b) const { + return a + t*(b-a); + } + + Bounds3f Bounds(const Bounds3f &allb) const { + + const auto& pMin = reinterpret_cast(allb.pMin); + const auto& pMax = reinterpret_cast(allb.pMax); + + return {Vector3f(lerp(qb[0][0] / 65535.f, pMin.x, pMax.x), + lerp(qb[0][1] / 65535.f, pMin.y, pMax.y), + lerp(qb[0][2] / 65535.f, pMin.z, pMax.z)), + Vector3f(lerp(qb[1][0] / 65535.f, pMin.x, pMax.x), + lerp(qb[1][1] / 65535.f, pMin.y, pMax.y), + lerp(qb[1][2] / 65535.f, pMin.z, pMax.z))}; + } + + float Importance(Vector3f p, Vector3f n, const Bounds3f &allb) const { + Bounds3f bounds = Bounds(allb); + float cosTheta_o = CosTheta_o(), cosTheta_e = CosTheta_e(); + // Return importance for light bounds at reference point + // Compute clamped squared distance to reference point + Vector3f pc = (bounds.pMin + bounds.pMax) / 2; + float d2 = lengthSquared(p - pc); + d2 = fmaxf(d2, length(bounds.diagonal()) / 2); + + // Define cosine and sine clamped subtraction lambdas + auto cosSubClamped = [](float sinTheta_a, float cosTheta_a, float sinTheta_b, float cosTheta_b) -> float { + if (cosTheta_a > cosTheta_b) + return 1; + return cosTheta_a * cosTheta_b + sinTheta_a * sinTheta_b; + }; // cos( theta_a - theta_b ) + + auto sinSubClamped = [](float sinTheta_a, float cosTheta_a, float sinTheta_b, float cosTheta_b) -> float { + if (cosTheta_a > cosTheta_b) + return 0; + return sinTheta_a * cosTheta_b - cosTheta_a * sinTheta_b; + }; // sin( theta_a - theta_b ) + + // Compute sine and cosine of angle to vector _w_, $\theta_\roman{w}$ + Vector3f wi = normalize(p - pc); + float cosTheta_w = dot(Vector3f(w), wi); + if (meta.doubleSided) + cosTheta_w = fabsf(cosTheta_w); + float sinTheta_w = SafeSqrt(1 - Sqr(cosTheta_w)); + + // Compute $\cos\,\theta_\roman{\+b}$ for reference point + float cosTheta_b = BoundSubtendedDirections(bounds, p).cosTheta; + float sinTheta_b = SafeSqrt(1 - Sqr(cosTheta_b)); + + // Compute $\cos\,\theta'$ and test against $\cos\,\theta_\roman{e}$ + float sinTheta_o = SafeSqrt(1 - Sqr(cosTheta_o)); + float cosTheta_x = cosSubClamped(sinTheta_w, cosTheta_w, sinTheta_o, cosTheta_o); + float sinTheta_x = sinSubClamped(sinTheta_w, cosTheta_w, sinTheta_o, cosTheta_o); + float cosThetap = cosSubClamped(sinTheta_x, cosTheta_x, sinTheta_b, cosTheta_b); + if (cosThetap <= cosTheta_e || cosThetap < 0.0f) + return 0; + + // Return final importance at reference point + float importance = phi * cosThetap / d2; + DCHECK(importance >= -1e-3f); + + if (n[0]!=0 && n[1]!=0 && n[2]!=0) { + + float cosTheta_i = AbsDot(wi, n); + float sinTheta_i = SafeSqrt(1 - Sqr(cosTheta_i)); + float cosThetap_i = cosSubClamped(sinTheta_i, cosTheta_i, sinTheta_b, cosTheta_b); + importance *= cosThetap_i; + } + + importance = fmaxf(importance, 0); + return importance; + } + + private: + // CompactLightBounds Private Methods + static unsigned int QuantizeCos(float c) { + DCHECK(c >= -1 && c <= 1); + return floorf(32767.f * ((c + 1) / 2)); + } + + static float QuantizeBounds(float c, float min, float max) { + DCHECK(c >= min && c <= max); + if (min == max) + return 0; + return 65535.f * clamp((c - min) / (max - min), 0.0f, 1.0f); + } + + // CompactLightBounds Private Members + OctahedralVector w; + float phi = 0; + struct { + unsigned int qCosTheta_o:15; + unsigned int qCosTheta_e:15; + bool doubleSided:1; + } meta; + uint16_t qb[2][3]; +}; + +// LightBVHNode Definition +struct alignas(32) LightTreeNode { + + LightTreeNode() = default; + + static LightTreeNode MakeLeaf(unsigned int lightIndex, const CompactLightBounds &cb) { + return LightTreeNode{cb, {lightIndex, 1}}; + } + + static LightTreeNode MakeInterior(unsigned int child1Index, + const CompactLightBounds &cb) { + return LightTreeNode{cb, {child1Index, 0}}; + } + + CompactLightBounds lightBounds; + struct { + unsigned int childOrLightIndex : 31; + unsigned int isLeaf : 1; + } meta; +}; + +struct SelectedLight { + uint32_t lightIdx; + float prob = 0.0f; +}; + +// BVHLightSampler Definition +struct LightTreeSampler { + public: + +#ifndef __CUDACC_RTC__ + + LightTreeSampler(std::vector &lights); + + inline void upload(CUdeviceptr &lightBitTrailsPtr, CUdeviceptr &lightTreeNodesPtr) + { + { + size_t byte_length = sizeof( lightBitTrails[0] ) * lightBitTrails.size(); + + CUDA_CHECK( cudaMalloc(reinterpret_cast( &lightBitTrailsPtr ), byte_length) ); + CUDA_CHECK( cudaMemcpy(reinterpret_cast( lightBitTrailsPtr ), + lightBitTrails.data(), byte_length, cudaMemcpyHostToDevice) ); + } + { + size_t byte_length = sizeof( nodes[0] ) * nodes.size(); + + CUDA_CHECK( cudaMalloc(reinterpret_cast( &lightTreeNodesPtr ), byte_length) ); + CUDA_CHECK( cudaMemcpy(reinterpret_cast( lightTreeNodesPtr ), + nodes.data(), byte_length, cudaMemcpyHostToDevice) ); + } + } + +#endif + + inline Bounds3f bounds() { return rootBounds; } + + inline SelectedLight sample(float u, const Vector3f& p, const Vector3f& n) + { + // Traverse light BVH to sample light + #ifndef __CUDACC_RTC__ + if (nodes.empty()) return SelectedLight(); + #else + if (nullptr == nodes) return SelectedLight(); + #endif + + int nodeIndex = 0; + float pmf = 1.0f; + + while (true) { + // Process light BVH node for light sampling + LightTreeNode& node = nodes[nodeIndex]; + if (!node.meta.isLeaf) { + // Compute light BVH child node importances + const LightTreeNode *child0 = &nodes[nodeIndex + 1]; + const LightTreeNode *child1 = &nodes[node.meta.childOrLightIndex]; + + float ci[3] = { 0.0f, + child0->lightBounds.Importance(p, n, rootBounds), + child1->lightBounds.Importance(p, n, rootBounds) }; + + DCHECK(ci[1] >= 0 && ci[2] >= 0); + + if (ci[1] == 0 && ci[2] == 0) + return {}; + + // Randomly sample light BVH child node + float nodePMF; + + int child = [&u, &ci, &nodePMF]() { + + auto sum = ci[1] + ci[2]; + auto up = u * sum; + + int pick_idx = up= 0 && node.lightBounds.Importance(p, n, rootBounds) > 0) { + return SelectedLight{ node.meta.childOrLightIndex, pmf}; + } + + return {}; + } + } + + return {}; + } + + float PMF(const Vector3f &p, const Vector3f &n, const uint32_t lightIdx) const { + + // Initialize local variables for BVH traversal for PMF computation + uint32_t bitTrail = lightBitTrails[lightIdx]; + + int nodeIndex = 0; + float pmf = 1.0f; + + // Compute light's PMF by walking down tree nodes to the light + while (true) { + const LightTreeNode *node = &nodes[nodeIndex]; + if (node->meta.isLeaf) { + DCHECK(lightIdx == node->meta.childOrLightIndex); + return pmf; + } + + // Compute child importances and update PMF for current node + const LightTreeNode *child0 = &nodes[nodeIndex + 1]; + const LightTreeNode *child1 = &nodes[node->meta.childOrLightIndex]; + float ci[2] = {child0->lightBounds.Importance(p, n, rootBounds), + child1->lightBounds.Importance(p, n, rootBounds)}; + DCHECK(ci[bitTrail & 1] > 0); + pmf *= ci[bitTrail & 1] / (ci[0] + ci[1]); + + // Use _bitTrail_ to find next node index and update its value + nodeIndex = (bitTrail & 1) ? node->meta.childOrLightIndex : (nodeIndex + 1); + bitTrail >>= 1; + } + } + + private: + +#ifndef __CUDACC_RTC__ + + std::pair buildTree(std::vector> &bvhLights, + int start, int end, uint32_t bitTrail, int depth); +#endif + + float EvaluateCost(const LightBounds &b, const Bounds3f &bounds, int dim) const { + // Evaluate direction bounds measure for _LightBounds_ + float theta_o = acosf(b.cosTheta_o); + float theta_e = acosf(b.cosTheta_e); + float theta_w = fminf(theta_o + theta_e, M_PIf); + float sinTheta_o = SafeSqrt(1 - Sqr(b.cosTheta_o)); + float M_omega = 2 * M_PIf * (1 - b.cosTheta_o) + + M_PIf / 2 * + (2 * theta_w * sinTheta_o - cosf(theta_o - 2 * theta_w) - + 2 * theta_o * sinTheta_o + b.cosTheta_o); + + float Kr = MaxComponentValue(bounds.diagonal()) / bounds.diagonal()[dim]; + + return b.phi * M_omega * Kr * b.bounds.area(); + } + +// BVHLightSampler Private Members +#ifndef __CUDACC_RTC__ + std::vector lightBitTrails{}; + std::vector nodes{}; +#else + uint32_t *lightBitTrails; + LightTreeNode *nodes; +#endif + Bounds3f rootBounds; +}; + +} // namespace \ No newline at end of file diff --git a/zenovis/xinxinoptix/OptiXStuff.h b/zenovis/xinxinoptix/OptiXStuff.h index 64f0b17279..49f9f81f14 100644 --- a/zenovis/xinxinoptix/OptiXStuff.h +++ b/zenovis/xinxinoptix/OptiXStuff.h @@ -1,5 +1,6 @@ #pragma once +#include #include // Needs to be included before gl_interop #include @@ -43,7 +44,9 @@ #include #include #include -#include "ies/ies_loader.h" + +#include "ies/ies.h" + #include "zeno/utils/fileio.h" #include "zeno/extra/TempNode.h" #include "zeno/types/PrimitiveObject.h" @@ -184,7 +187,7 @@ inline bool createModule(OptixModule &m, OptixDeviceContext &context, const char const std::vector compilerOptions { "-std=c++17", "-default-device", //"-extra-device-vectorization" #if !defined( NDEBUG ) - //"-lineinfo", "-G"//"--dopt=on", + "-lineinfo", //"-G"//"--dopt=on", #endif //"--gpu-architecture=compute_60", //"--relocatable-device-code=true" @@ -494,7 +497,7 @@ inline bool preloadVDB(const zeno::TextureObjectVDB& texVDB, std::filesystem::path filePath = path; if ( !std::filesystem::exists(filePath) ) { - std::cout << filePath.string() << " doesn't exist"; + std::cout << filePath.string() << " doesn't exist" << std::endl; return false; } @@ -555,27 +558,28 @@ inline bool preloadVDB(const zeno::TextureObjectVDB& texVDB, return true; } -inline std::vector IES2HDR(const std::string& path) + +inline std::vector loadIES(const std::string& path, float& coneAngle) { - IESFileInfo info; - auto IESBuffer = zeno::file_get_binary(path); - IESBuffer.push_back(0); + std::filesystem::path filePath = path; - IESLoadHelper IESLoader; - if (!IESLoader.load(IESBuffer.data(), IESBuffer.size() - 1, info)) { - std::string l = "IESLoader.load"; - throw std::runtime_error(l); + if ( !std::filesystem::exists(filePath) ) { + std::cout << filePath.string() << " doesn't exist" << std::endl; + return {}; } - std::vector img; - img.resize(256 * 3); + auto iesBuffer = zeno::file_get_binary(path); + auto iesString = std::string(iesBuffer.data()); + //std::cout << iesString << std::endl; - if (!IESLoader.saveAs1D(info, img.data(), 256, 3)) { - std::string l = "IESLoader.saveAs1D"; - throw std::runtime_error(l); - } + blender::IESFile iesFile; + iesFile.load(iesString); - return img; + std::vector iesData(iesFile.packed_size()); + iesFile.pack(iesData.data()); + coneAngle = iesFile.coneAngle(); + + return iesData; } inline std::map> g_tex; inline std::map g_tex_last_write_time; @@ -585,6 +589,13 @@ inline std::map sky_ny_map; inline std::map sky_avg_map; +struct WrapperIES { + raii ptr; + float coneAngle = 0.0f; +}; + +inline std::map g_ies; + inline std::map> sky_cdf_map; inline std::map> sky_pdf_map; inline std::map> sky_start_map; @@ -618,7 +629,7 @@ inline void calc_sky_cdf_map(int nx, int ny, int nc, T *img) { auto color = zeno::vec3f(img[idx2+0], img[idx2+1], img[idx2+2]); illum = zeno::dot(color, zeno::vec3f(0.33333333f,0.33333333f, 0.33333333f)); //illum = illum > 0.5? illum : 0.0f; - illum = abs(illum) * sin(3.1415926f*((float)jj + 0.5f)/(float)ny); + illum = abs(illum) * sinf(3.1415926f*((float)jj + 0.5f)/(float)ny); sky_cdf[idx] += illum + (idx>0? sky_cdf[idx-1]:0); skypdf[idx] = illum; @@ -693,8 +704,21 @@ inline void addTexture(std::string path) free(rgba); } else if (zeno::ends_with(path, ".ies", false)) { - auto img = IES2HDR(path); - g_tex[path] = makeCudaTexture(img.data(), 256, 1, 3); + float coneAngle; + auto iesd = loadIES(path, coneAngle); + + if (iesd.empty()) { + g_ies.erase(path); + return; + } + + raii iesBuffer; + size_t data_length = iesd.size() * sizeof(float); + + CUDA_CHECK( cudaMalloc( reinterpret_cast( &iesBuffer.reset() ), data_length) ); + CUDA_CHECK( cudaMemcpy( reinterpret_cast( (CUdeviceptr)iesBuffer ), iesd.data(), data_length, cudaMemcpyHostToDevice ) ); + + g_ies[path] = {std::move(iesBuffer), coneAngle }; } else if (zeno::getSession().nodeClasses.count("ReadPNG16") > 0 && zeno::ends_with(path, ".png", false)) { auto outs = zeno::TempNodeSimpleCaller("ReadPNG16") diff --git a/zenovis/xinxinoptix/PTKernel.cu b/zenovis/xinxinoptix/PTKernel.cu index 8fe81a2ddf..880d32f239 100644 --- a/zenovis/xinxinoptix/PTKernel.cu +++ b/zenovis/xinxinoptix/PTKernel.cu @@ -130,187 +130,164 @@ extern "C" __global__ void __raygen__rg() prd.eventseed = eventseed; prd.opacity = 0; prd.flags = 0; - prd.next_ray_is_going_inside = false; prd.maxDistance = 1e16f; prd.medium = DisneyBSDF::PhaseFunctions::vacuum; - prd.depth = 0; - prd.diffDepth = 0; - prd.isSS = false; - prd.direction = ray_direction; - prd.curMatIdx = 0; - prd.test_distance = false; - prd.ss_alpha_queue[0] = vec3(-1.0f); - prd.minSpecRough = 0.01; - prd.samplePdf = 1.0f; - prd.first_hit_type = 0; - prd.hitEnv = false; - auto tmin = prd.trace_tmin; - auto ray_mask = prd._mask_; - - // prd.channelPDF= vec3(1.0f/3.0f); - // prd.ss_alpha = vec3(0.0f); - // prd.sigma_t = vec3(0.0f); - - - - //if constexpr(params.denoise) - if (params.denoise) - { - prd.trace_denoise_albedo = true; - prd.trace_denoise_normal = true; - } - - // Primary Ray - traceRadianceMasked(params.handle, ray_origin, ray_direction, tmin, prd.maxDistance, ray_mask, &prd); - - tmp_albedo = prd.tmp_albedo; - tmp_normal = prd.tmp_normal; - - prd.trace_denoise_albedo = false; - prd.trace_denoise_normal = false; - - for(;;) - { - prd.radiance_d = make_float3(0); - prd.radiance_s = make_float3(0); - prd.radiance_t = make_float3(0); - tmin = prd.trace_tmin; - prd.trace_tmin = 0; - - ray_mask = prd._mask_; - prd._mask_ = EverythingMask; - - if(prd.countEmitted==false || prd.depth>0) { - auto temp_radiance = prd.radiance * prd.attenuation2; - - //float upperBound = prd.fromDiff?1.0f:1.0f; - float3 clampped = clamp(vec3(temp_radiance), vec3(0), vec3(10)); - - result += prd.depth>1?clampped:temp_radiance; - if(prd.depth==1 && prd.hitEnv == false) - { + prd.origin = ray_origin; + prd.direction = ray_direction; + + prd.depth = 0; + prd.diffDepth = 0; + prd.isSS = false; + prd.curMatIdx = 0; + prd.test_distance = false; + prd.ss_alpha_queue[0] = vec3(-1.0f); + prd.minSpecRough = 0.01; + prd.samplePdf = 1.0f; + prd.first_hit_type = 0; + prd.hitEnv = false; + auto _tmin_ = prd._tmin_; + auto _mask_ = prd._mask_; + + //if constexpr(params.denoise) + if (params.denoise) + { + prd.trace_denoise_albedo = true; + prd.trace_denoise_normal = true; + } + + // Primary Ray + traceRadiance(params.handle, ray_origin, ray_direction, _tmin_, prd.maxDistance, &prd, _mask_); + + tmp_albedo = prd.tmp_albedo; + tmp_normal = prd.tmp_normal; + + prd.trace_denoise_albedo = false; + prd.trace_denoise_normal = false; + + for(;;) + { + prd.radiance_d = make_float3(0); + prd.radiance_s = make_float3(0); + prd.radiance_t = make_float3(0); + + _tmin_ = prd._tmin_; + _mask_ = prd._mask_; + + prd._tmin_ = 0; + prd._mask_ = EverythingMask; + + ray_origin = prd.origin; + ray_direction = prd.direction; + + if(prd.countEmitted==false || prd.depth>0) { + auto temp_radiance = prd.radiance * prd.attenuation2; + + //float upperBound = prd.fromDiff?1.0f:1.0f; + float3 clampped = clamp(vec3(temp_radiance), vec3(0), vec3(10)); + + result += prd.depth>1?clampped:temp_radiance; + if(prd.depth==1 && prd.hitEnv == false) + { result_d += prd.radiance_d * prd.attenuation2; result_s += prd.radiance_s * prd.attenuation2; result_t += prd.radiance_t * prd.attenuation2; - } - if(prd.depth>1 || (prd.depth==1 && prd.hitEnv == true)) { + } + if(prd.depth>1 || (prd.depth==1 && prd.hitEnv == true)) { result_d += prd.first_hit_type == 1 ? clampped : make_float3(0, 0, 0); result_s += prd.first_hit_type == 2 ? clampped : make_float3(0, 0, 0); result_t += prd.first_hit_type == 3 ? clampped : make_float3(0, 0, 0); - } - - // fire without smoke requires this line to work. - } - - prd.radiance = make_float3(0); - prd.emission = make_float3(0); - - if (ray_mask != EverythingMask && ray_mask != NothingMask) { - //ray_origin = prd.origin; - //ray_direction = prd.direction; - traceRadianceMasked(params.handle, ray_origin, ray_direction, tmin, prd.maxDistance, ray_mask, &prd); - continue; // trace again with same parameters but different mask - } - - if(prd.countEmitted==true && prd.depth>0){ - prd.done = true; - } - - if( prd.done || params.simpleRender==true){ - break; - } - - if(prd.depth>16){ - //float RRprob = clamp(length(prd.attenuation)/1.732f,0.01f,0.9f); - float RRprob = clamp(length(prd.attenuation),0.1f, 0.95f); - if(rnd(prd.seed) > RRprob || prd.depth > 16){ - prd.done=true; - } else { - prd.attenuation = prd.attenuation / RRprob; - } - } - if(prd.countEmitted == true) - prd.passed = true; - - ray_origin = prd.origin; - ray_direction = prd.direction; - - // result_d = make_float3(0,0,0); - // result_s = make_float3(0,0,0); - // result_t = make_float3(0,0,0); - - traceRadianceMasked(params.handle, ray_origin, ray_direction, tmin, prd.maxDistance, ray_mask, &prd); - } - result_b += prd.first_hit_type == 0 ? make_float3(0, 0, 0) - : make_float3(1, 1, 1); - seed = prd.seed; - } - while( --i ); - - float3 accum_color = result / static_cast( params.samples_per_launch ); - float3 accum_color_d = result_d / static_cast( params.samples_per_launch ); - float3 accum_color_s = result_s / static_cast( params.samples_per_launch ); - float3 accum_color_t = result_t / static_cast( params.samples_per_launch ); - float3 accum_color_b = result_b / static_cast( params.samples_per_launch ); - //const uint3 launch_index = optixGetLaunchIndex(); - //launch_index.y * params.width + launch_index.x; - - if( subframe_index > 0 ) - { - const float a = 1.0f / static_cast( subframe_index+1 ); - const float3 accum_color_prev = make_float3( params.accum_buffer[ image_index ]); - const float3 accum_color_prev_d = make_float3( params.accum_buffer_D[ image_index ]); - const float3 accum_color_prev_s = make_float3( params.accum_buffer_S[ image_index ]); - const float3 accum_color_prev_t = make_float3( params.accum_buffer_T[ image_index ]); - const float3 accum_color_prev_b = make_float3( params.accum_buffer_B[ image_index ]); - accum_color = lerp( accum_color_prev, accum_color, a ); - accum_color_d = lerp( accum_color_prev_d, accum_color_d, a ); - accum_color_s = lerp( accum_color_prev_s, accum_color_s, a ); - accum_color_t = lerp( accum_color_prev_t, accum_color_t, a ); - accum_color_b = lerp( accum_color_prev_b, accum_color_b, a ); - - if (params.denoise) { - - const float3 accum_albedo_prev = params.albedo_buffer[ image_index ]; - tmp_albedo = lerp(accum_albedo_prev, tmp_albedo, a); - - const float3 accum_normal_prev = params.normal_buffer[ image_index ]; - tmp_normal = lerp(accum_normal_prev, tmp_normal, a); - } - } - - /*if (launch_index.x == 0) {*/ - /*printf("%p\n", params.accum_buffer);*/ - /*printf("%p\n", params.frame_buffer);*/ - /*}*/ - params.accum_buffer[ image_index ] = make_float4( accum_color, 1.0f); - params.accum_buffer_D[ image_index ] = make_float4( accum_color_d, 1.0f); - params.accum_buffer_S[ image_index ] = make_float4( accum_color_s, 1.0f); - params.accum_buffer_T[ image_index ] = make_float4( accum_color_t, 1.0f); - params.accum_buffer_B[ image_index ] = make_float4( accum_color_b, 1.0f); - //vec3 aecs_fitted = ACESFitted(vec3(accum_color), 2.2); - float3 out_color = accum_color; - float3 out_color_d = accum_color_d; - float3 out_color_s = accum_color_s; - float3 out_color_t = accum_color_t; - float3 out_color_b = accum_color_b; - params.frame_buffer[ image_index ] = make_color ( out_color ); - params.frame_buffer_C[ image_index ] = accum_color; - params.frame_buffer_D[ image_index ] = accum_color_d; - params.frame_buffer_S[ image_index ] = accum_color_s; - params.frame_buffer_T[ image_index ] = accum_color_t; - params.frame_buffer_B[ image_index ] = accum_color_b; - - if (params.denoise) { - params.albedo_buffer[ image_index ] = tmp_albedo; - params.normal_buffer[ image_index ] = tmp_normal; - } -// } -// } + } + + } + + prd.radiance = make_float3(0); + prd.emission = make_float3(0); + + if(prd.countEmitted==true && prd.depth>0){ + prd.done = true; + } + + if( prd.done || params.simpleRender==true){ + break; + } + + if(prd.depth>16) { + float RRprob = clamp(length(prd.attenuation),0.1f, 0.95f); + if(rnd(prd.seed) > RRprob || prd.depth > 24) { + prd.done=true; + } else { + prd.attenuation = prd.attenuation / RRprob; + } + } + if(prd.countEmitted == true) + prd.passed = true; + + traceRadiance(params.handle, ray_origin, ray_direction, _tmin_, prd.maxDistance, &prd, _mask_); + } + result_b += prd.first_hit_type == 0 ? make_float3(0, 0, 0) + : make_float3(1, 1, 1); + seed = prd.seed; + } + while( --i ); + + auto samples_per_launch = static_cast( params.samples_per_launch ); + + float3 accum_color = result / samples_per_launch; + float3 accum_color_d = result_d / samples_per_launch; + float3 accum_color_s = result_s / samples_per_launch; + float3 accum_color_t = result_t / samples_per_launch; + float3 accum_color_b = result_b / samples_per_launch; + + if( subframe_index > 0 ) + { + const float a = 1.0f / static_cast( subframe_index+1 ); + const float3 accum_color_prev = make_float3( params.accum_buffer[ image_index ]); + const float3 accum_color_prev_d = make_float3( params.accum_buffer_D[ image_index ]); + const float3 accum_color_prev_s = make_float3( params.accum_buffer_S[ image_index ]); + const float3 accum_color_prev_t = make_float3( params.accum_buffer_T[ image_index ]); + const float3 accum_color_prev_b = make_float3( params.accum_buffer_B[ image_index ]); + accum_color = lerp( accum_color_prev, accum_color, a ); + accum_color_d = lerp( accum_color_prev_d, accum_color_d, a ); + accum_color_s = lerp( accum_color_prev_s, accum_color_s, a ); + accum_color_t = lerp( accum_color_prev_t, accum_color_t, a ); + accum_color_b = lerp( accum_color_prev_b, accum_color_b, a ); + + if (params.denoise) { + + const float3 accum_albedo_prev = params.albedo_buffer[ image_index ]; + tmp_albedo = lerp(accum_albedo_prev, tmp_albedo, a); + + const float3 accum_normal_prev = params.normal_buffer[ image_index ]; + tmp_normal = lerp(accum_normal_prev, tmp_normal, a); + } + } + + params.accum_buffer[ image_index ] = make_float4( accum_color, 1.0f); + params.accum_buffer_D[ image_index ] = make_float4( accum_color_d, 1.0f); + params.accum_buffer_S[ image_index ] = make_float4( accum_color_s, 1.0f); + params.accum_buffer_T[ image_index ] = make_float4( accum_color_t, 1.0f); + params.accum_buffer_B[ image_index ] = make_float4( accum_color_b, 1.0f); + //vec3 aecs_fitted = ACESFitted(vec3(accum_color), 2.2); + float3 out_color = accum_color; + float3 out_color_d = accum_color_d; + float3 out_color_s = accum_color_s; + float3 out_color_t = accum_color_t; + float3 out_color_b = accum_color_b; + params.frame_buffer[ image_index ] = make_color ( out_color ); + params.frame_buffer_C[ image_index ] = accum_color; + params.frame_buffer_D[ image_index ] = accum_color_d; + params.frame_buffer_S[ image_index ] = accum_color_s; + params.frame_buffer_T[ image_index ] = accum_color_t; + params.frame_buffer_B[ image_index ] = accum_color_b; + + if (params.denoise) { + params.albedo_buffer[ image_index ] = tmp_albedo; + params.normal_buffer[ image_index ] = tmp_normal; + } } extern "C" __global__ void __miss__radiance() @@ -325,7 +302,7 @@ extern "C" __global__ void __miss__radiance() prd->attenuation2 = prd->attenuation; prd->passed = false; prd->countEmitted = false; - prd->CH = 0.0; + if(prd->medium != DisneyBSDF::PhaseFunctions::isotropic){ float upperBound = 100.0f; float envPdf = 0.0f; @@ -344,13 +321,16 @@ extern "C" __global__ void __miss__radiance() 0.0 ); + float misWeight = BRDFBasics::PowerHeuristic(prd->samplePdf,envPdf); misWeight = misWeight>0.0f?misWeight:0.0f; misWeight = envPdf>0.0f?misWeight:1.0f; misWeight = prd->depth>=1?misWeight:1.0f; misWeight = prd->samplePdf>0.0f?misWeight:1.0f; - prd->radiance = misWeight * skysample ; + + prd->radiance = misWeight * skysample; + if (params.show_background == false) { prd->radiance = prd->depth>=1?prd->radiance:make_float3(0,0,0); } diff --git a/zenovis/xinxinoptix/SDK/cuda/GeometryData.h b/zenovis/xinxinoptix/SDK/cuda/GeometryData.h deleted file mode 100644 index ef8a593fae..0000000000 --- a/zenovis/xinxinoptix/SDK/cuda/GeometryData.h +++ /dev/null @@ -1,78 +0,0 @@ -// -// Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of NVIDIA CORPORATION nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -#pragma once - -#include - - -struct GeometryData -{ - enum Type - { - TRIANGLE_MESH = 0, - SPHERE = 1, - LINEAR_CURVE_ARRAY = 2, - QUADRATIC_CURVE_ARRAY = 3, - CUBIC_CURVE_ARRAY = 4, - }; - - - struct TriangleMesh - { - GenericBufferView indices; - BufferView positions; - BufferView normals; - BufferView texcoords; - }; - - - struct Sphere - { - float3 center; - float radius; - }; - - - struct Curves - { - BufferView strand_u; // strand_u at segment start per segment - GenericBufferView strand_i; // strand index per segment - BufferView strand_info; // info.x = segment base - // info.y = strand length (segments) - }; - - - Type type; - - union - { - TriangleMesh triangle_mesh; - Sphere sphere; - Curves curves; - }; -}; diff --git a/zenovis/xinxinoptix/SDK/cuda/Light.h b/zenovis/xinxinoptix/SDK/cuda/Light.h deleted file mode 100644 index 0edc288f90..0000000000 --- a/zenovis/xinxinoptix/SDK/cuda/Light.h +++ /dev/null @@ -1,71 +0,0 @@ -// -// Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of NVIDIA CORPORATION nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -#pragma once -#include - -struct Light -{ - Light() {} - - enum class Falloff : int - { - NONE = 0, - LINEAR, - QUADRATIC - }; - - - enum class Type : int - { - POINT = 0, - AMBIENT = 1 - }; - - struct Point - { - float3 color CONST_STATIC_INIT( { 1.0f, 1.0f, 1.0f } ); - float intensity CONST_STATIC_INIT( 1.0f ); - float3 position CONST_STATIC_INIT( {} ); - Falloff falloff CONST_STATIC_INIT( Falloff::QUADRATIC ); - }; - - - struct Ambient - { - float3 color CONST_STATIC_INIT( {1.0f, 1.0f, 1.0f} ); - }; - - - Type type; - - union - { - Point point; - Ambient ambient; - }; -}; diff --git a/zenovis/xinxinoptix/SDK/cuda/LocalGeometry.h b/zenovis/xinxinoptix/SDK/cuda/LocalGeometry.h deleted file mode 100644 index 89fbb368d6..0000000000 --- a/zenovis/xinxinoptix/SDK/cuda/LocalGeometry.h +++ /dev/null @@ -1,152 +0,0 @@ -// -// Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of NVIDIA CORPORATION nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -#pragma once - -#include - -#include -#include -#include -#include -#include -#include - - -struct LocalGeometry -{ - float3 P; - float3 N; - float3 Ng; - float2 UV; - float3 dndu; - float3 dndv; - float3 dpdu; - float3 dpdv; -}; - - -SUTIL_HOSTDEVICE LocalGeometry getLocalGeometry( const GeometryData& geometry_data ) -{ - LocalGeometry lgeom; - switch( geometry_data.type ) - { - case GeometryData::TRIANGLE_MESH: - { - const GeometryData::TriangleMesh& mesh_data = geometry_data.triangle_mesh; - - const unsigned int prim_idx = optixGetPrimitiveIndex(); - const float2 barys = optixGetTriangleBarycentrics(); - - uint3 tri = make_uint3(0u, 0u, 0u); - if( mesh_data.indices.elmt_byte_size == 4 ) - { - const uint3* indices = reinterpret_cast( mesh_data.indices.data ); - tri = indices[ prim_idx ]; - } - else - { - const unsigned short* indices = reinterpret_cast( mesh_data.indices.data ); - const unsigned short idx0 = indices[prim_idx * 3 + 0]; - const unsigned short idx1 = indices[prim_idx * 3 + 1]; - const unsigned short idx2 = indices[prim_idx * 3 + 2]; - tri = make_uint3( idx0, idx1, idx2 ); - } - - const float3 P0 = mesh_data.positions[ tri.x ]; - const float3 P1 = mesh_data.positions[ tri.y ]; - const float3 P2 = mesh_data.positions[ tri.z ]; - lgeom.P = ( 1.0f-barys.x-barys.y)*P0 + barys.x*P1 + barys.y*P2; - lgeom.P = optixTransformPointFromObjectToWorldSpace( lgeom.P ); - - float2 UV0, UV1, UV2; - if( mesh_data.texcoords ) - { - UV0 = mesh_data.texcoords[ tri.x ]; - UV1 = mesh_data.texcoords[ tri.y ]; - UV2 = mesh_data.texcoords[ tri.z ]; - lgeom.UV = ( 1.0f-barys.x-barys.y)*UV0 + barys.x*UV1 + barys.y*UV2; - } - else - { - UV0 = make_float2( 0.0f, 0.0f ); - UV1 = make_float2( 0.0f, 1.0f ); - UV2 = make_float2( 1.0f, 0.0f ); - lgeom.UV = barys; - } - - lgeom.Ng = normalize( cross( P1-P0, P2-P0 ) ); - lgeom.Ng = optixTransformNormalFromObjectToWorldSpace( lgeom.Ng ); - - float3 N0, N1, N2; - if( mesh_data.normals ) - { - N0 = mesh_data.normals[ tri.x ]; - N1 = mesh_data.normals[ tri.y ]; - N2 = mesh_data.normals[ tri.z ]; - lgeom.N = ( 1.0f-barys.x-barys.y)*N0 + barys.x*N1 + barys.y*N2; - lgeom.N = normalize( optixTransformNormalFromObjectToWorldSpace( lgeom.N ) ); - } - else - { - lgeom.N = N0 = N1 = N2 = lgeom.Ng; - } - - const float du1 = UV0.x - UV2.x; - const float du2 = UV1.x - UV2.x; - const float dv1 = UV0.y - UV2.y; - const float dv2 = UV1.y - UV2.y; - - const float3 dp1 = P0 - P2; - const float3 dp2 = P1 - P2; - - const float3 dn1 = N0 - N2; - const float3 dn2 = N1 - N2; - - const float det = du1*dv2 - dv1*du2; - - const float invdet = 1.f / det; - lgeom.dpdu = ( dv2 * dp1 - dv1 * dp2) * invdet; - lgeom.dpdv = (-du2 * dp1 + du1 * dp2) * invdet; - lgeom.dndu = ( dv2 * dn1 - dv1 * dn2) * invdet; - lgeom.dndv = (-du2 * dn1 + du1 * dn2) * invdet; - - - break; - } - case GeometryData::SPHERE: - { - break; - } - default: break; - } - - - return lgeom; -} - - diff --git a/zenovis/xinxinoptix/SDK/cuda/MaterialData.h b/zenovis/xinxinoptix/SDK/cuda/MaterialData.h deleted file mode 100644 index 27e5010256..0000000000 --- a/zenovis/xinxinoptix/SDK/cuda/MaterialData.h +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of NVIDIA CORPORATION nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include - - -struct MaterialData -{ - enum Type - { - PBR = 0 - }; - - - struct Pbr - { - float4 base_color = { 1.0f, 1.0f, 1.0f, 1.0f }; - float metallic = 1.0f; - float roughness = 1.0f; - - cudaTextureObject_t base_color_tex = 0; - cudaTextureObject_t metallic_roughness_tex = 0; - cudaTextureObject_t normal_tex = 0; - }; - - Type type; - - union - { - Pbr pbr; - }; -}; diff --git a/zenovis/xinxinoptix/SDK/cuda/climits.h b/zenovis/xinxinoptix/SDK/cuda/climits.h new file mode 100644 index 0000000000..73b412b557 --- /dev/null +++ b/zenovis/xinxinoptix/SDK/cuda/climits.h @@ -0,0 +1,103 @@ +//===----------------------------------------------------------------------===// +// +// Part of libcu++, the C++ Standard Library for your entire system, +// under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _CUDA_CLIMITS +#define _CUDA_CLIMITS + +#if !defined(__CUDACC_RTC__) && defined(__linux__) + #include + #include + #include +#else + + #define CHAR_BIT 8 + #define SCHAR_MIN (-128) + #define SCHAR_MAX 127 + #define UCHAR_MAX 255 + #define __CHAR_UNSIGNED__ ('\xff' > 0) // CURSED + #if __CHAR_UNSIGNED__ + #define CHAR_MIN 0 + #define CHAR_MAX UCHAR_MAX + #else + #define CHAR_MIN SCHAR_MIN + #define CHAR_MAX SCHAR_MAX + #endif + #define SHRT_MIN (-SHRT_MAX - 1) + #define SHRT_MAX 0x7fff + #define USHRT_MAX 0xffff + #define INT_MIN (-INT_MAX - 1) + #define INT_MAX 0x7fffffff + #define UINT_MAX 0xffffffff + #define LONG_MIN (-LONG_MAX - 1) + #ifdef __LP64__ + #define LONG_MAX LLONG_MAX + #define ULONG_MAX ULLONG_MAX + #else + #define LONG_MAX INT_MAX + #define ULONG_MAX UINT_MAX + #endif + #define LLONG_MIN (-LLONG_MAX - 1) + #define LLONG_MAX 0x7fffffffffffffff + #define ULLONG_MAX 0xffffffffffffffff + + #define __FLT_RADIX__ 2 + #define __FLT_MANT_DIG__ 24 + #define __FLT_DIG__ 6 + #define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F + #define __FLT_MAX__ 3.40282346638528859811704183484516925e+38F + #define __FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F + #define __FLT_MIN_EXP__ (-125) + #define __FLT_MIN_10_EXP__ (-37) + #define __FLT_MAX_EXP__ 128 + #define __FLT_MAX_10_EXP__ 38 + #define __FLT_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F + #define __DBL_MANT_DIG__ 53 + #define __DBL_DIG__ 15 + #define __DBL_MIN__ 2.22507385850720138309023271733240406e-308 + #define __DBL_MAX__ 1.79769313486231570814527423731704357e+308 + #define __DBL_EPSILON__ 2.22044604925031308084726333618164062e-16 + #define __DBL_MIN_EXP__ (-1021) + #define __DBL_MIN_10_EXP__ (-307) + #define __DBL_MAX_EXP__ 1024 + #define __DBL_MAX_10_EXP__ 308 + #define __DBL_DENORM_MIN__ 4.94065645841246544176568792868221372e-324 + +#endif //__CUDACC_RTC__ + +#if defined(__CUDACC_RTC__) + + template + static __device__ __forceinline__ + _To __cowchild_cast(_From __from) + { + static_assert(sizeof(_From) == sizeof(_To), ""); + union __cast { _From __from; _To __to; }; + __cast __c; + __c.__from = __from; + return __c.__to; + } + + #define __builtin_huge_valf() __cowchild_cast(0x7f800000) + #define __builtin_nanf(__dummy) __cowchild_cast(0x7fc00000) + #define __builtin_nansf(__dummy) __cowchild_cast(0x7fa00000) + #define __builtin_huge_val() __cowchild_cast(0x7ff0000000000000) + #define __builtin_nan(__dummy) __cowchild_cast(0x7ff8000000000000) + #define __builtin_nans(__dummy) __cowchild_cast(0x7ff4000000000000) + +#endif + +// ICC defines __CHAR_BIT__ by default +// accept that, but assert it is what we expect +#ifdef __CHAR_BIT__ + static_assert(__CHAR_BIT__ == 8, ""); +#else + #define __CHAR_BIT__ 8 +#endif + +#endif //_CUDA_CLIMITS diff --git a/zenovis/xinxinoptix/SDK/cuda/cstdint.h b/zenovis/xinxinoptix/SDK/cuda/cstdint.h new file mode 100644 index 0000000000..fc1cfc8f01 --- /dev/null +++ b/zenovis/xinxinoptix/SDK/cuda/cstdint.h @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// Part of libcu++, the C++ Standard Library for your entire system, +// under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _CUDA_CSTDINT +#define _CUDA_CSTDINT + +#ifndef __CUDACC_RTC__ + #include + #include +#else + typedef signed char int8_t; + typedef unsigned char uint8_t; + typedef signed short int16_t; + typedef unsigned short uint16_t; + typedef signed int int32_t; + typedef unsigned int uint32_t; + typedef signed long long int64_t; + typedef unsigned long long uint64_t; + +#define _LIBCUDACXX_ADDITIONAL_INTS(N) \ + typedef int##N##_t int_fast##N##_t; \ + typedef uint##N##_t uint_fast##N##_t; \ + typedef int##N##_t int_least##N##_t; \ + typedef uint##N##_t uint_least##N##_t + + _LIBCUDACXX_ADDITIONAL_INTS(8); + _LIBCUDACXX_ADDITIONAL_INTS(16); + _LIBCUDACXX_ADDITIONAL_INTS(32); + _LIBCUDACXX_ADDITIONAL_INTS(64); +#undef _LIBCUDACXX_ADDITIONAL_INTS + + typedef int64_t intptr_t; + typedef uint64_t uintptr_t; + typedef int64_t intmax_t; + typedef uint64_t uintmax_t; + + #define INT8_MIN SCHAR_MIN + #define INT16_MIN SHRT_MIN + #define INT32_MIN INT_MIN + #define INT64_MIN LLONG_MIN + #define INT8_MAX SCHAR_MAX + #define INT16_MAX SHRT_MAX + #define INT32_MAX INT_MAX + #define INT64_MAX LLONG_MAX + #define UINT8_MAX UCHAR_MAX + #define UINT16_MAX USHRT_MAX + #define UINT32_MAX UINT_MAX + #define UINT64_MAX ULLONG_MAX + #define INT_FAST8_MIN SCHAR_MIN + #define INT_FAST16_MIN SHRT_MIN + #define INT_FAST32_MIN INT_MIN + #define INT_FAST64_MIN LLONG_MIN + #define INT_FAST8_MAX SCHAR_MAX + #define INT_FAST16_MAX SHRT_MAX + #define INT_FAST32_MAX INT_MAX + #define INT_FAST64_MAX LLONG_MAX + #define UINT_FAST8_MAX UCHAR_MAX + #define UINT_FAST16_MAX USHRT_MAX + #define UINT_FAST32_MAX UINT_MAX + #define UINT_FAST64_MAX ULLONG_MAX + + #define INT8_C(X) ((int_least8_t)(X)) + #define INT16_C(X) ((int_least16_t)(X)) + #define INT32_C(X) ((int_least32_t)(X)) + #define INT64_C(X) ((int_least64_t)(X)) + #define UINT8_C(X) ((uint_least8_t)(X)) + #define UINT16_C(X) ((uint_least16_t)(X)) + #define UINT32_C(X) ((uint_least32_t)(X)) + #define UINT64_C(X) ((uint_least64_t)(X)) + #define INTMAX_C(X) ((intmax_t)(X)) + #define UINTMAX_C(X) ((uintmax_t)(X)) +#endif //__CUDACC_RTC__ + +// #include "climits.h" + +#endif //_CUDA_CSTDINT diff --git a/zenovis/xinxinoptix/SDK/cuda/random.h b/zenovis/xinxinoptix/SDK/cuda/random.h index 0608f73b97..ce6784de0f 100644 --- a/zenovis/xinxinoptix/SDK/cuda/random.h +++ b/zenovis/xinxinoptix/SDK/cuda/random.h @@ -60,6 +60,13 @@ static __host__ __device__ __inline__ unsigned int lcg2(unsigned int &prev) return prev; } +static __host__ __device__ __inline__ unsigned int lcg32(unsigned int &prev) +{ + /* implicit mod 2^32 */ + prev = (1103515245 * (prev) + 12345); + return prev; +} + // Generate random float in [0, 1) static __host__ __device__ __inline__ float rnd(unsigned int &prev) { diff --git a/zenovis/xinxinoptix/SDK/cuda/sphere.cu b/zenovis/xinxinoptix/SDK/cuda/sphere.cu deleted file mode 100644 index 15c369b223..0000000000 --- a/zenovis/xinxinoptix/SDK/cuda/sphere.cu +++ /dev/null @@ -1,97 +0,0 @@ -// -// Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of NVIDIA CORPORATION nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include - -#include - -#include "sphere.h" - -#define float3_as_ints( u ) float_as_int( u.x ), float_as_int( u.y ), float_as_int( u.z ) - -extern "C" __global__ void __intersection__sphere() -{ - const sphere::SphereHitGroupData* hit_group_data = reinterpret_cast( optixGetSbtDataPointer() ); - - const float3 ray_orig = optixGetWorldRayOrigin(); - const float3 ray_dir = optixGetWorldRayDirection(); - const float ray_tmin = optixGetRayTmin(); - const float ray_tmax = optixGetRayTmax(); - - const float3 O = ray_orig - hit_group_data->sphere.center; - const float l = 1.0f / length( ray_dir ); - const float3 D = ray_dir * l; - const float radius = hit_group_data->sphere.radius; - - float b = dot( O, D ); - float c = dot( O, O ) - radius * radius; - float disc = b * b - c; - if( disc > 0.0f ) - { - float sdisc = sqrtf( disc ); - float root1 = ( -b - sdisc ); - float root11 = 0.0f; - bool check_second = true; - - const bool do_refine = fabsf( root1 ) > ( 10.0f * radius ); - - if( do_refine ) - { - // refine root1 - float3 O1 = O + root1 * D; - b = dot( O1, D ); - c = dot( O1, O1 ) - radius * radius; - disc = b * b - c; - - if( disc > 0.0f ) - { - sdisc = sqrtf( disc ); - root11 = ( -b - sdisc ); - } - } - - float t; - float3 normal; - t = ( root1 + root11 ) * l; - if( t > ray_tmin && t < ray_tmax ) - { - normal = ( O + ( root1 + root11 ) * D ) / radius; - if( optixReportIntersection( t, 0, float3_as_ints( normal ), float_as_int( radius ) ) ) - check_second = false; - } - - if( check_second ) - { - float root2 = ( -b + sdisc ) + ( do_refine ? root1 : 0 ); - t = root2 * l; - normal = ( O + root2 * D ) / radius; - if( t > ray_tmin && t < ray_tmax ) - optixReportIntersection( t, 0, float3_as_ints( normal ), float_as_int( radius ) ); - } - } -} diff --git a/zenovis/xinxinoptix/SDK/cuda/sphere.h b/zenovis/xinxinoptix/SDK/cuda/sphere.h deleted file mode 100644 index 1f3d1f3c46..0000000000 --- a/zenovis/xinxinoptix/SDK/cuda/sphere.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of NVIDIA CORPORATION nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include "GeometryData.h" - -namespace sphere { - -const unsigned int NUM_ATTRIBUTE_VALUES = 4u; - -struct SphereHitGroupData -{ - GeometryData::Sphere sphere; -}; - -} // namespace sphere diff --git a/zenovis/xinxinoptix/SDK/cuda/util.h b/zenovis/xinxinoptix/SDK/cuda/util.h deleted file mode 100644 index dfefbc2671..0000000000 --- a/zenovis/xinxinoptix/SDK/cuda/util.h +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of NVIDIA CORPORATION nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -#pragma once - -#ifndef __CUDACC_RTC__ -#include -#endif - -#define if_pixel( x_, y_ ) \ - const uint3 launch_idx__ = optixGetLaunchIndex(); \ - if( launch_idx__.x == (x_) && launch_idx__.y == (y_) ) \ - -#define print_pixel( x_, y_, str, ... ) \ -do \ -{ \ - const uint3 launch_idx = optixGetLaunchIndex(); \ - if( launch_idx.x == (x_) && launch_idx.y == (y_) ) \ - { \ - printf( str, __VA_ARGS__ ); \ - } \ -} while(0); - - diff --git a/zenovis/xinxinoptix/SDK/cuda/whitted.cu b/zenovis/xinxinoptix/SDK/cuda/whitted.cu deleted file mode 100644 index 6b22cee8de..0000000000 --- a/zenovis/xinxinoptix/SDK/cuda/whitted.cu +++ /dev/null @@ -1,197 +0,0 @@ -// -// Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of NVIDIA CORPORATION nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -#include - -#include -#include -#include -#include - -#include "whitted_cuda.h" - -//------------------------------------------------------------------------------ -// -// -// -//------------------------------------------------------------------------------ - -extern "C" __global__ void __raygen__pinhole() -{ - const uint3 launch_idx = optixGetLaunchIndex(); - const uint3 launch_dims = optixGetLaunchDimensions(); - const float3 eye = whitted::params.eye; - const float3 U = whitted::params.U; - const float3 V = whitted::params.V; - const float3 W = whitted::params.W; - const int subframe_index = whitted::params.subframe_index; - - // - // Generate camera ray - // - unsigned int seed = tea<4>( launch_idx.y * launch_dims.x + launch_idx.x, subframe_index ); - - // The center of each pixel is at fraction (0.5,0.5) - const float2 subpixel_jitter = - subframe_index == 0 ? make_float2( 0.5f, 0.5f ) : make_float2( rnd( seed ), rnd( seed ) ); - - const float2 d = - 2.0f - * make_float2( ( static_cast( launch_idx.x ) + subpixel_jitter.x ) / static_cast( launch_dims.x ), - ( static_cast( launch_idx.y ) + subpixel_jitter.y ) / static_cast( launch_dims.y ) ) - - 1.0f; - const float3 ray_direction = normalize( d.x * U + d.y * V + W ); - const float3 ray_origin = eye; - - // - // Trace camera ray - // - whitted::PayloadRadiance payload; - payload.result = make_float3( 0.0f ); - payload.importance = 1.0f; - payload.depth = 0.0f; - - traceRadiance( whitted::params.handle, ray_origin, ray_direction, - 0.01f, // tmin // TODO: smarter offset - 1e16f, // tmax - &payload ); - - // - // Update results - // TODO: timview mode - // - const unsigned int image_index = launch_idx.y * launch_dims.x + launch_idx.x; - float3 accum_color = payload.result; - - if( subframe_index > 0 ) - { - const float a = 1.0f / static_cast( subframe_index + 1 ); - const float3 accum_color_prev = make_float3( whitted::params.accum_buffer[image_index] ); - accum_color = lerp( accum_color_prev, accum_color, a ); - } - whitted::params.accum_buffer[image_index] = make_float4( accum_color, 1.0f ); - whitted::params.frame_buffer[image_index] = make_color( accum_color ); -} - - -extern "C" __global__ void __miss__constant_radiance() -{ - whitted::setPayloadResult( whitted::params.miss_color ); -} - - -extern "C" __global__ void __closesthit__occlusion() -{ - whitted::setPayloadOcclusion( true ); -} - - -extern "C" __global__ void __closesthit__radiance() -{ - const whitted::HitGroupData* hit_group_data = reinterpret_cast( optixGetSbtDataPointer() ); - const LocalGeometry geom = getLocalGeometry( hit_group_data->geometry_data ); - - // - // Retrieve material data - // - float3 base_color = make_float3( hit_group_data->material_data.pbr.base_color ); - if( hit_group_data->material_data.pbr.base_color_tex ) - base_color *= whitted::linearize( - make_float3( tex2D( hit_group_data->material_data.pbr.base_color_tex, geom.UV.x, geom.UV.y ) ) ); - - float metallic = hit_group_data->material_data.pbr.metallic; - float roughness = hit_group_data->material_data.pbr.roughness; - float4 mr_tex = make_float4( 1.0f ); - if( hit_group_data->material_data.pbr.metallic_roughness_tex ) - // MR tex is (occlusion, roughness, metallic ) - mr_tex = tex2D( hit_group_data->material_data.pbr.metallic_roughness_tex, geom.UV.x, geom.UV.y ); - roughness *= mr_tex.y; - metallic *= mr_tex.z; - - // - // Convert to material params - // - const float F0 = 0.04f; - const float3 diff_color = base_color * ( 1.0f - F0 ) * ( 1.0f - metallic ); - const float3 spec_color = lerp( make_float3( F0 ), base_color, metallic ); - const float alpha = roughness * roughness; - - // - // compute direct lighting - // - - float3 N = geom.N; - if( hit_group_data->material_data.pbr.normal_tex ) - { - const float4 NN = - 2.0f * tex2D( hit_group_data->material_data.pbr.normal_tex, geom.UV.x, geom.UV.y ) - make_float4( 1.0f ); - N = normalize( NN.x * normalize( geom.dpdu ) + NN.y * normalize( geom.dpdv ) + NN.z * geom.N ); - } - - float3 result = make_float3( 0.0f ); - - for( int i = 0; i < whitted::params.lights.count; ++i ) - { - Light light = whitted::params.lights[i]; - if( light.type == Light::Type::POINT ) - { - // TODO: optimize - const float L_dist = length( light.point.position - geom.P ); - const float3 L = ( light.point.position - geom.P ) / L_dist; - const float3 V = -normalize( optixGetWorldRayDirection() ); - const float3 H = normalize( L + V ); - const float N_dot_L = dot( N, L ); - const float N_dot_V = dot( N, V ); - const float N_dot_H = dot( N, H ); - const float V_dot_H = dot( V, H ); - - if( N_dot_L > 0.0f && N_dot_V > 0.0f ) - { - const float tmin = 0.001f; // TODO - const float tmax = L_dist - 0.001f; // TODO - const bool occluded = whitted::traceOcclusion( whitted::params.handle, geom.P, L, tmin, tmax ); - if( !occluded ) - { - const float3 F = whitted::schlick( spec_color, V_dot_H ); - const float G_vis = whitted::vis( N_dot_L, N_dot_V, alpha ); - const float D = whitted::ggxNormal( N_dot_H, alpha ); - - const float3 diff = ( 1.0f - F ) * diff_color / M_PIf; - const float3 spec = F * G_vis * D; - - result += light.point.color * light.point.intensity * N_dot_L * ( diff + spec ); - } - } - } - else if( light.type == Light::Type::AMBIENT ) - { - result += light.ambient.color * base_color; - } - } - - whitted::setPayloadResult( result ); -} diff --git a/zenovis/xinxinoptix/SDK/cuda/whitted.h b/zenovis/xinxinoptix/SDK/cuda/whitted.h deleted file mode 100644 index 01c085a497..0000000000 --- a/zenovis/xinxinoptix/SDK/cuda/whitted.h +++ /dev/null @@ -1,91 +0,0 @@ -// -// Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of NVIDIA CORPORATION nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -#pragma once - -#include - -#include -#include -#include -#include - -namespace whitted -{ - -const unsigned int NUM_PAYLOAD_VALUES = 4u; - - -struct HitGroupData -{ - GeometryData geometry_data; - MaterialData material_data; -}; - - -enum RayType -{ - RAY_TYPE_RADIANCE = 0, - RAY_TYPE_OCCLUSION = 1, - RAY_TYPE_COUNT = 2 -}; - - -struct LaunchParams -{ - unsigned int width; - unsigned int height; - unsigned int subframe_index; - float4* accum_buffer; - uchar4* frame_buffer; - int max_depth; - - float3 eye; - float3 U; - float3 V; - float3 W; - - BufferView lights; - float3 miss_color; - OptixTraversableHandle handle; -}; - - -struct PayloadRadiance -{ - float3 result; - float importance; - int depth; -}; - - -struct PayloadOcclusion -{ -}; - - -} // end namespace whitted diff --git a/zenovis/xinxinoptix/SDK/cuda/whitted_cuda.h b/zenovis/xinxinoptix/SDK/cuda/whitted_cuda.h deleted file mode 100644 index 982082dfde..0000000000 --- a/zenovis/xinxinoptix/SDK/cuda/whitted_cuda.h +++ /dev/null @@ -1,160 +0,0 @@ -// -// Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of NVIDIA CORPORATION nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include - -#include "whitted.h" - -namespace whitted { - -extern "C" { -__constant__ whitted::LaunchParams params; -} - -//------------------------------------------------------------------------------ -// -// GGX/smith shading helpers -// TODO: move into header so can be shared by path tracer and bespoke renderers -// -//------------------------------------------------------------------------------ - -__device__ __forceinline__ float3 schlick( const float3 spec_color, const float V_dot_H ) -{ - return spec_color + ( make_float3( 1.0f ) - spec_color ) * powf( 1.0f - V_dot_H, 5.0f ); -} - -__device__ __forceinline__ float vis( const float N_dot_L, const float N_dot_V, const float alpha ) -{ - const float alpha_sq = alpha*alpha; - - const float ggx0 = N_dot_L * sqrtf( N_dot_V*N_dot_V * ( 1.0f - alpha_sq ) + alpha_sq ); - const float ggx1 = N_dot_V * sqrtf( N_dot_L*N_dot_L * ( 1.0f - alpha_sq ) + alpha_sq ); - - return 2.0f * N_dot_L * N_dot_V / (ggx0+ggx1); -} - - -__device__ __forceinline__ float ggxNormal( const float N_dot_H, const float alpha ) -{ - const float alpha_sq = alpha*alpha; - const float N_dot_H_sq = N_dot_H*N_dot_H; - const float x = N_dot_H_sq*( alpha_sq - 1.0f ) + 1.0f; - return alpha_sq/( M_PIf*x*x ); -} - - -__device__ __forceinline__ float3 linearize( float3 c ) -{ - return make_float3( - powf( c.x, 2.2f ), - powf( c.y, 2.2f ), - powf( c.z, 2.2f ) - ); -} - - -//------------------------------------------------------------------------------ -// -// -// -//------------------------------------------------------------------------------ - - -static __forceinline__ __device__ void traceRadiance( - OptixTraversableHandle handle, - float3 ray_origin, - float3 ray_direction, - float tmin, - float tmax, - whitted::PayloadRadiance* payload - ) -{ - unsigned int u0=0, u1=0, u2=0, u3=0; - optixTrace( - handle, - ray_origin, ray_direction, - tmin, - tmax, - 0.0f, // rayTime - OptixVisibilityMask( 1 ), - OPTIX_RAY_FLAG_NONE, - whitted::RAY_TYPE_RADIANCE, // SBT offset - whitted::RAY_TYPE_COUNT, // SBT stride - whitted::RAY_TYPE_RADIANCE, // missSBTIndex - u0, u1, u2, u3 ); - - payload->result.x = __int_as_float( u0 ); - payload->result.y = __int_as_float( u1 ); - payload->result.z = __int_as_float( u2 ); - payload->depth = u3; -} - - - -static __forceinline__ __device__ bool traceOcclusion( - OptixTraversableHandle handle, - float3 ray_origin, - float3 ray_direction, - float tmin, - float tmax - ) -{ - unsigned int occluded = 0u; - optixTrace( - handle, - ray_origin, - ray_direction, - tmin, - tmax, - 0.0f, // rayTime - OptixVisibilityMask( 1 ), - OPTIX_RAY_FLAG_TERMINATE_ON_FIRST_HIT, - whitted::RAY_TYPE_OCCLUSION, // SBT offset - whitted::RAY_TYPE_COUNT, // SBT stride - whitted::RAY_TYPE_OCCLUSION, // missSBTIndex - occluded ); - return occluded; -} - - -__forceinline__ __device__ void setPayloadResult( float3 p ) -{ - optixSetPayload_0( float_as_int( p.x ) ); - optixSetPayload_1( float_as_int( p.y ) ); - optixSetPayload_2( float_as_int( p.z ) ); -} - - -__forceinline__ __device__ void setPayloadOcclusion( bool occluded ) -{ - optixSetPayload_0( static_cast( occluded ) ); -} - -} // namespace whitted diff --git a/zenovis/xinxinoptix/SDK/sutil/Scene.cpp b/zenovis/xinxinoptix/SDK/sutil/Scene.cpp deleted file mode 100644 index b47890ce41..0000000000 --- a/zenovis/xinxinoptix/SDK/sutil/Scene.cpp +++ /dev/null @@ -1,1409 +0,0 @@ -// -// Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -#include -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -#include -// are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of NVIDIA CORPORATION nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -//#define TINYGLTF_IMPLEMENTATION -//#define STB_IMAGE_IMPLEMENTATION // Implementation in sutil.cpp -//#define STB_IMAGE_WRITE_IMPLEMENTATION // -#if defined( WIN32 ) -# pragma warning( push ) -# pragma warning( disable : 4267 ) -#endif -//#include -#if defined( WIN32 ) -# pragma warning( pop ) -#endif - -#include -#include -#include -#include -#include - -namespace sutil -{ - -namespace -{ - -float3 make_float3_from_double( double x, double y, double z ) -{ - return make_float3( static_cast( x ), static_cast( y ), static_cast( z ) ); -} - -float4 make_float4_from_double( double x, double y, double z, double w ) -{ - return make_float4( static_cast( x ), static_cast( y ), static_cast( z ), static_cast( w ) ); -} - -typedef Record HitGroupRecord; - -void context_log_cb( unsigned int level, const char* tag, const char* message, void* /*cbdata */) -{ - std::cerr << "[" << std::setw( 2 ) << level << "][" << std::setw( 12 ) << tag << "]: " - << message << "\n"; -} - -#if 0 -template -BufferView bufferViewFromGLTF( const tinygltf::Model& model, Scene& scene, const int32_t accessor_idx ) -{ - if( accessor_idx == -1 ) - return BufferView(); - - const auto& gltf_accessor = model.accessors[ accessor_idx ]; - const auto& gltf_buffer_view = model.bufferViews[ gltf_accessor.bufferView ]; - - const int32_t elmt_byte_size = - gltf_accessor.componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT ? 2 : - gltf_accessor.componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT ? 4 : - gltf_accessor.componentType == TINYGLTF_COMPONENT_TYPE_FLOAT ? 4 : - 0; - if( !elmt_byte_size ) - throw Exception( "gltf accessor component type not supported" ); - - const CUdeviceptr buffer_base = scene.getBuffer( gltf_buffer_view.buffer ); - BufferView buffer_view; - buffer_view.data = buffer_base + gltf_buffer_view.byteOffset + gltf_accessor.byteOffset; - buffer_view.byte_stride = static_cast( gltf_buffer_view.byteStride ); - buffer_view.count = static_cast( gltf_accessor.count ); - buffer_view.elmt_byte_size = static_cast( elmt_byte_size ); - - return buffer_view; -} - -void processGLTFNode( - Scene& scene, - const tinygltf::Model& model, - const tinygltf::Node& gltf_node, - const Matrix4x4& parent_matrix - ) -{ - const Matrix4x4 translation = gltf_node.translation.empty() ? - Matrix4x4::identity() : - Matrix4x4::translate( make_float3_from_double( - gltf_node.translation[0], - gltf_node.translation[1], - gltf_node.translation[2] - ) ); - - const Matrix4x4 rotation = gltf_node.rotation.empty() ? - Matrix4x4::identity() : - Quaternion( - static_cast( gltf_node.rotation[3] ), - static_cast( gltf_node.rotation[0] ), - static_cast( gltf_node.rotation[1] ), - static_cast( gltf_node.rotation[2] ) - ).rotationMatrix(); - - const Matrix4x4 scale = gltf_node.scale.empty() ? - Matrix4x4::identity() : - Matrix4x4::scale( make_float3_from_double( - gltf_node.scale[0], - gltf_node.scale[1], - gltf_node.scale[2] - ) ); - - std::vector gltf_matrix; - for( double x : gltf_node.matrix ) - gltf_matrix.push_back( static_cast( x ) ); - const Matrix4x4 matrix = gltf_node.matrix.empty() ? - Matrix4x4::identity() : - Matrix4x4( reinterpret_cast( gltf_matrix.data() ) ).transpose(); - - const Matrix4x4 node_xform = parent_matrix * matrix * translation * rotation * scale ; - - if( gltf_node.camera != -1 ) - { - const auto& gltf_camera = model.cameras[ gltf_node.camera ]; - std::cerr << "Processing camera '" << gltf_camera.name << "'\n" - << "\ttype: " << gltf_camera.type << "\n"; - if( gltf_camera.type != "perspective" ) - { - std::cerr << "\tskipping non-perpective camera\n"; - return; - } - - const float3 eye = make_float3( node_xform*make_float4_from_double( 0.0f, 0.0f, 0.0f, 1.0f ) ); - const float3 up = make_float3( node_xform*make_float4_from_double( 0.0f, 1.0f, 0.0f, 0.0f ) ); - const float yfov = static_cast( gltf_camera.perspective.yfov ) * 180.0f / static_cast( M_PI ); - - std::cerr << "\teye : " << eye.x << ", " << eye.y << ", " << eye.z << std::endl; - std::cerr << "\tup : " << up.x << ", " << up.y << ", " << up.z << std::endl; - std::cerr << "\tfov : " << yfov << std::endl; - std::cerr << "\taspect: " << gltf_camera.perspective.aspectRatio << std::endl; - - Camera camera; - camera.setFovY ( yfov ); - camera.setAspectRatio( static_cast( gltf_camera.perspective.aspectRatio ) ); - camera.setEye ( eye ); - camera.setUp ( up ); - scene.addCamera( camera ); - } - else if( gltf_node.mesh != -1 ) - { - const auto& gltf_mesh = model.meshes[ gltf_node.mesh ]; - std::cerr << "Processing glTF mesh: '" << gltf_mesh.name << "'\n"; - std::cerr << "\tNum mesh primitive groups: " << gltf_mesh.primitives.size() << std::endl; - for( auto& gltf_primitive : gltf_mesh.primitives ) - { - if( gltf_primitive.mode != TINYGLTF_MODE_TRIANGLES ) // Ignore non-triangle meshes - { - std::cerr << "\tNon-triangle primitive: skipping\n"; - continue; - } - - auto mesh = std::make_shared(); - scene.addMesh( mesh ); - - - mesh->name = gltf_mesh.name; - mesh->indices.push_back( bufferViewFromGLTF( model, scene, gltf_primitive.indices ) ); - mesh->material_idx.push_back( gltf_primitive.material ); - mesh->transform = node_xform; - std::cerr << "\t\tNum triangles: " << mesh->indices.back().count / 3 << std::endl; - - assert( gltf_primitive.attributes.find( "POSITION" ) != gltf_primitive.attributes.end() ); - const int32_t pos_accessor_idx = gltf_primitive.attributes.at( "POSITION" ); - mesh->positions.push_back( bufferViewFromGLTF( model, scene, pos_accessor_idx ) ); - - const auto& pos_gltf_accessor = model.accessors[ pos_accessor_idx ]; - mesh->object_aabb = Aabb( - make_float3_from_double( - pos_gltf_accessor.minValues[0], - pos_gltf_accessor.minValues[1], - pos_gltf_accessor.minValues[2] - ), - make_float3_from_double( - pos_gltf_accessor.maxValues[0], - pos_gltf_accessor.maxValues[1], - pos_gltf_accessor.maxValues[2] - ) ); - mesh->world_aabb = mesh->object_aabb; - mesh->world_aabb.transform( node_xform ); - - auto normal_accessor_iter = gltf_primitive.attributes.find( "NORMAL" ) ; - if( normal_accessor_iter != gltf_primitive.attributes.end() ) - { - std::cerr << "\t\tHas vertex normals: true\n"; - mesh->normals.push_back( bufferViewFromGLTF( model, scene, normal_accessor_iter->second ) ); - } - else - { - std::cerr << "\t\tHas vertex normals: false\n"; - mesh->normals.push_back( bufferViewFromGLTF( model, scene, -1 ) ); - } - - auto texcoord_accessor_iter = gltf_primitive.attributes.find( "TEXCOORD_0" ) ; - if( texcoord_accessor_iter != gltf_primitive.attributes.end() ) - { - std::cerr << "\t\tHas texcoords: true\n"; - mesh->texcoords.push_back( bufferViewFromGLTF( model, scene, texcoord_accessor_iter->second ) ); - } - else - { - std::cerr << "\t\tHas texcoords: false\n"; - mesh->texcoords.push_back( bufferViewFromGLTF( model, scene, -1 ) ); - } - } - } - else if( !gltf_node.children.empty() ) - { - for( int32_t child : gltf_node.children ) - { - processGLTFNode( scene, model, model.nodes[child], node_xform ); - } - } -} - -#endif -} // end anon namespace -#if 0 - - -void loadScene( const std::string& filename, Scene& scene ) -{ - scene.cleanup(); - - tinygltf::Model model; - tinygltf::TinyGLTF loader; - std::string err; - std::string warn; - - bool ret = loader.LoadASCIIFromFile( &model, &err, &warn, filename ); - if( !warn.empty() ) - std::cerr << "glTF WARNING: " << warn << std::endl; - if( !ret ) - { - std::cerr << "Failed to load GLTF scene '" << filename << "': " << err << std::endl; - throw Exception( err.c_str() ); - } - - // - // Process buffer data first -- buffer views will reference this list - // - for( const auto& gltf_buffer : model.buffers ) - { - const uint64_t buf_size = gltf_buffer.data.size(); - std::cerr << "Processing glTF buffer '" << gltf_buffer.name << "'\n" - << "\tbyte size: " << buf_size << "\n" - << "\turi : " << gltf_buffer.uri << std::endl; - - scene.addBuffer( buf_size, gltf_buffer.data.data() ); - } - - // - // Images -- just load all up front for simplicity - // - for( const auto& gltf_image : model.images ) - { - std::cerr << "Processing image '" << gltf_image.name << "'\n" - << "\t(" << gltf_image.width << "x" << gltf_image.height << ")x" << gltf_image.component << "\n" - << "\tbits: " << gltf_image.bits << std::endl; - - assert( gltf_image.component == 4 ); - assert( gltf_image.bits == 8 || gltf_image.bits == 16 ); - - scene.addImage( - gltf_image.width, - gltf_image.height, - gltf_image.bits, - gltf_image.component, - gltf_image.image.data() - ); - } - - // - // Textures -- refer to previously loaded images - // - for( const auto& gltf_texture : model.textures ) - { - if( gltf_texture.sampler == -1 ) - { - scene.addSampler( cudaAddressModeWrap, cudaAddressModeWrap, cudaFilterModeLinear, gltf_texture.source ); - continue; - } - - const auto& gltf_sampler = model.samplers[ gltf_texture.sampler ]; - - const cudaTextureAddressMode address_s = gltf_sampler.wrapS == GL_CLAMP_TO_EDGE ? cudaAddressModeClamp : - gltf_sampler.wrapS == GL_MIRRORED_REPEAT ? cudaAddressModeMirror : - cudaAddressModeWrap; - const cudaTextureAddressMode address_t = gltf_sampler.wrapT == GL_CLAMP_TO_EDGE ? cudaAddressModeClamp : - gltf_sampler.wrapT == GL_MIRRORED_REPEAT ? cudaAddressModeMirror : - cudaAddressModeWrap; - const cudaTextureFilterMode filter = gltf_sampler.minFilter == GL_NEAREST ? cudaFilterModePoint : - cudaFilterModeLinear; - scene.addSampler( address_s, address_t, filter, gltf_texture.source ); - } - - // - // Materials - // - for( auto& gltf_material : model.materials ) - { - std::cerr << "Processing glTF material: '" << gltf_material.name << "'\n"; - MaterialData::Pbr mtl; - - { - const auto base_color_it = gltf_material.values.find( "baseColorFactor" ); - if( base_color_it != gltf_material.values.end() ) - { - const tinygltf::ColorValue c = base_color_it->second.ColorFactor(); - mtl.base_color = make_float4_from_double( c[0], c[1], c[2], c[3] ); - std::cerr - << "\tBase color: (" - << mtl.base_color.x << ", " - << mtl.base_color.y << ", " - << mtl.base_color.z << ")\n"; - } - else - { - std::cerr << "\tUsing default base color factor\n"; - } - } - - { - const auto base_color_it = gltf_material.values.find( "baseColorTexture" ); - if( base_color_it != gltf_material.values.end() ) - { - std::cerr << "\tFound base color tex: " << base_color_it->second.TextureIndex() << "\n"; - mtl.base_color_tex = scene.getSampler( base_color_it->second.TextureIndex() ); - } - else - { - std::cerr << "\tNo base color tex\n"; - } - } - - { - const auto roughness_it = gltf_material.values.find( "roughnessFactor" ); - if( roughness_it != gltf_material.values.end() ) - { - mtl.roughness = static_cast( roughness_it->second.Factor() ); - std::cerr << "\tRougness: " << mtl.roughness << "\n"; - } - else - { - std::cerr << "\tUsing default roughness factor\n"; - } - } - - { - const auto metallic_it = gltf_material.values.find( "metallicFactor" ); - if( metallic_it != gltf_material.values.end() ) - { - mtl.metallic = static_cast( metallic_it->second.Factor() ); - std::cerr << "\tMetallic: " << mtl.metallic << "\n"; - } - else - { - std::cerr << "\tUsing default metallic factor\n"; - } - } - - { - const auto metallic_roughness_it = gltf_material.values.find( "metallicRoughnessTexture" ); - if( metallic_roughness_it != gltf_material.values.end() ) - { - std::cerr << "\tFound metallic roughness tex: " << metallic_roughness_it->second.TextureIndex() << "\n"; - mtl.metallic_roughness_tex = scene.getSampler( metallic_roughness_it->second.TextureIndex() ); - } - else - { - std::cerr << "\tNo metallic roughness tex\n"; - } - } - - { - const auto normal_it = gltf_material.additionalValues.find( "normalTexture" ); - if( normal_it != gltf_material.additionalValues.end() ) - { - std::cerr << "\tFound normal color tex: " << normal_it->second.TextureIndex() << "\n"; - mtl.normal_tex = scene.getSampler( normal_it->second.TextureIndex() ); - } - else - { - std::cerr << "\tNo normal tex\n"; - } - } - - scene.addMaterial( mtl ); - } - - // - // Process nodes - // - std::vector root_nodes( model.nodes.size(), 1 ); - for( auto& gltf_node : model.nodes ) - for( int32_t child : gltf_node.children ) - root_nodes[child] = 0; - - for( size_t i = 0; i < root_nodes.size(); ++i ) - { - if( !root_nodes[i] ) - continue; - auto& gltf_node = model.nodes[i]; - - processGLTFNode( scene, model, gltf_node, Matrix4x4::identity() ); - } -} -#endif - - -Scene::Scene( ) {} - - -Scene::~Scene( ) -{ - cleanup(); -} - - -void Scene::addBuffer( const uint64_t buf_size, const void* data ) -{ - CUdeviceptr buffer = 0; - CUDA_CHECK( cudaMalloc( reinterpret_cast( &buffer ), buf_size ) ); - CUDA_CHECK( cudaMemcpy( - reinterpret_cast( buffer ), - data, - buf_size, - cudaMemcpyHostToDevice - ) ); - m_buffers.push_back( buffer ); -} - - -void Scene::addImage( - const int32_t width, - const int32_t height, - const int32_t bits_per_component, - const int32_t num_components, - const void* data - ) -{ - // Allocate CUDA array in device memory - int32_t pitch; - cudaChannelFormatDesc channel_desc; - if( bits_per_component == 8 ) - { - pitch = width*num_components*sizeof(uint8_t); - channel_desc = cudaCreateChannelDesc(); - } - else if( bits_per_component == 16 ) - { - pitch = width*num_components*sizeof(uint16_t); - channel_desc = cudaCreateChannelDesc(); - } - else - { - throw Exception( "Unsupported bits/component in glTF image" ); - } - - - cudaArray_t cuda_array = nullptr; - CUDA_CHECK( cudaMallocArray( - &cuda_array, - &channel_desc, - width, - height, - 0 - ) ); - CUDA_CHECK( cudaMemcpy2DToArray( - cuda_array, - 0, // X offset - 0, // Y offset - data, - pitch, - pitch, - height, - cudaMemcpyHostToDevice - ) ); - m_images.push_back( cuda_array ); -} - - - void Scene::addSampler( - cudaTextureAddressMode address_s, - cudaTextureAddressMode address_t, - cudaTextureFilterMode filter, - const int32_t image_idx - ) -{ - cudaResourceDesc res_desc = {}; - res_desc.resType = cudaResourceTypeArray; - res_desc.res.array.array = getImage( image_idx ); - - cudaTextureDesc tex_desc = {}; - tex_desc.addressMode[0] = address_s == GL_CLAMP_TO_EDGE ? cudaAddressModeClamp : - address_s == GL_MIRRORED_REPEAT ? cudaAddressModeMirror : - cudaAddressModeWrap; - tex_desc.addressMode[1] = address_t == GL_CLAMP_TO_EDGE ? cudaAddressModeClamp : - address_t == GL_MIRRORED_REPEAT ? cudaAddressModeMirror : - cudaAddressModeWrap; - tex_desc.filterMode = filter == GL_NEAREST ? cudaFilterModePoint : - cudaFilterModeLinear; - tex_desc.readMode = cudaReadModeNormalizedFloat; - tex_desc.normalizedCoords = 1; - tex_desc.maxAnisotropy = 1; - tex_desc.maxMipmapLevelClamp = 99; - tex_desc.minMipmapLevelClamp = 0; - tex_desc.mipmapFilterMode = cudaFilterModePoint; - tex_desc.borderColor[0] = 1.0f; - tex_desc.sRGB = 0; // TODO: glTF assumes sRGB for base_color -- handle in shader - - // Create texture object - cudaTextureObject_t cuda_tex = 0; - CUDA_CHECK( cudaCreateTextureObject(&cuda_tex, &res_desc, &tex_desc, nullptr ) ); - m_samplers.push_back( cuda_tex ); -} - - -CUdeviceptr Scene::getBuffer( int32_t buffer_index ) const -{ - return m_buffers[ buffer_index ]; -} - - -cudaArray_t Scene::getImage( int32_t image_index ) const -{ - return m_images[ image_index ]; -} - - -cudaTextureObject_t Scene::getSampler( int32_t sampler_index ) const -{ - return m_samplers[ sampler_index ]; -} - - -void Scene::finalize() -{ - createContext(); - buildMeshAccels(); - buildInstanceAccel(); - createPTXModule(); - createProgramGroups(); - createPipeline(); - createSBT(); - - m_scene_aabb.invalidate(); - for( const auto mesh: m_meshes ) - m_scene_aabb.include( mesh->world_aabb ); - - if( !m_cameras.empty() ) - m_cameras.front().setLookat( m_scene_aabb.center() ); -} - - -void sutil::Scene::cleanup() -{ - // OptiX cleanup - if( m_pipeline ) - { - OPTIX_CHECK( optixPipelineDestroy( m_pipeline ) ); - m_pipeline = 0; - } - if( m_raygen_prog_group ) - { - OPTIX_CHECK( optixProgramGroupDestroy( m_raygen_prog_group ) ); - m_raygen_prog_group = 0; - } - if( m_radiance_miss_group ) - { - OPTIX_CHECK( optixProgramGroupDestroy( m_radiance_miss_group ) ); - m_radiance_miss_group = 0; - } - if( m_occlusion_miss_group ) - { - OPTIX_CHECK( optixProgramGroupDestroy( m_occlusion_miss_group ) ); - m_occlusion_miss_group = 0; - } - if( m_radiance_hit_group ) - { - OPTIX_CHECK( optixProgramGroupDestroy( m_radiance_hit_group ) ); - m_radiance_hit_group = 0; - } - if( m_occlusion_hit_group ) - { - OPTIX_CHECK( optixProgramGroupDestroy( m_occlusion_hit_group ) ); - m_occlusion_hit_group = 0; - } - if( m_ptx_module ) - { - OPTIX_CHECK( optixModuleDestroy( m_ptx_module ) ); - m_ptx_module = 0; - } - if( m_context ) - { - OPTIX_CHECK( optixDeviceContextDestroy( m_context ) ); - m_context = 0; - } - - // Free buffers for mesh (indices, positions, normals, texcoords) - for( CUdeviceptr& buffer : m_buffers ) - CUDA_CHECK( cudaFree( reinterpret_cast( buffer ) ) ); - m_buffers.clear(); - - // Destroy textures (base_color, metallic_roughness, normal) - for( cudaTextureObject_t& texture : m_samplers ) - CUDA_CHECK( cudaDestroyTextureObject( texture ) ); - m_samplers.clear(); - - for( cudaArray_t& image : m_images ) - CUDA_CHECK( cudaFreeArray( image ) ); - m_images.clear(); - - if( m_d_ias_output_buffer ) - { - CUDA_CHECK( cudaFree( reinterpret_cast( m_d_ias_output_buffer ) ) ); - m_d_ias_output_buffer = 0; - } - if( m_sbt.raygenRecord ) - { - CUDA_CHECK( cudaFree( reinterpret_cast( m_sbt.raygenRecord ) ) ); - m_sbt.raygenRecord = 0; - } - if( m_sbt.missRecordBase ) - { - CUDA_CHECK( cudaFree( reinterpret_cast( m_sbt.missRecordBase ) ) ); - m_sbt.missRecordBase = 0; - } - if( m_sbt.hitgroupRecordBase ) - { - CUDA_CHECK( cudaFree( reinterpret_cast( m_sbt.hitgroupRecordBase ) ) ); - m_sbt.hitgroupRecordBase = 0; - } - for( auto mesh : m_meshes ) - CUDA_CHECK( cudaFree( reinterpret_cast( mesh->d_gas_output ) ) ); - m_meshes.clear(); -} - - -sutil::Camera sutil::Scene::camera() const -{ - if( !m_cameras.empty() ) - { - std::cerr << "Returning first camera" << std::endl; - return m_cameras.front(); - } - - std::cerr << "Returning default camera" << std::endl; - Camera cam; - cam.setFovY( 45.0f ); - cam.setLookat( m_scene_aabb.center() ); - cam.setEye ( m_scene_aabb.center() + make_float3( 0.0f, 0.0f, 1.5f*m_scene_aabb.maxExtent() ) ); - return cam; -} - - -//------------------------------------------------------------------------------ -// -// -// -//------------------------------------------------------------------------------ - -void Scene::createContext() -{ - // Initialize CUDA - CUDA_CHECK( cudaFree( nullptr ) ); - - CUcontext cuCtx = nullptr; // zero means take the current context - OPTIX_CHECK( optixInit() ); - OptixDeviceContextOptions options = {}; - options.logCallbackFunction = &context_log_cb; - options.logCallbackLevel = 4; - OPTIX_CHECK( optixDeviceContextCreate( cuCtx, &options, &m_context ) ); -} - -namespace { -template -class CuBuffer -{ - public: - CuBuffer( size_t count = 0 ) { alloc( count ); } - ~CuBuffer() { free(); } - void alloc( size_t count ) - { - free(); - m_allocCount = m_count = count; - if( m_count ) - { - CUDA_CHECK( cudaMalloc( &m_ptr, m_allocCount * sizeof( T ) ) ); - } - } - void allocIfRequired( size_t count ) - { - if( count <= m_allocCount ) - { - m_count = count; - return; - } - alloc( count ); - } - CUdeviceptr get() const { return reinterpret_cast( m_ptr ); } - CUdeviceptr get( size_t index ) const { return reinterpret_cast( m_ptr + index ); } - void free() - { - m_count = 0; - m_allocCount = 0; - CUDA_CHECK( cudaFree( m_ptr ) ); - m_ptr = nullptr; - } - CUdeviceptr release() - { - m_count = 0; - m_allocCount = 0; - CUdeviceptr current = reinterpret_cast( m_ptr ); - m_ptr = nullptr; - return current; - } - void upload( const T* data ) - { - CUDA_CHECK( cudaMemcpy( m_ptr, data, m_count * sizeof( T ), cudaMemcpyHostToDevice ) ); - } - - void download( T* data ) const - { - CUDA_CHECK( cudaMemcpy( data, m_ptr, m_count * sizeof( T ), cudaMemcpyDeviceToHost ) ); - } - void downloadSub( size_t count, size_t offset, T* data ) const - { - assert( count + offset <= m_allocCount ); - CUDA_CHECK( cudaMemcpy( data, m_ptr + offset, count * sizeof( T ), cudaMemcpyDeviceToHost ) ); - } - size_t count() const { return m_count; } - size_t reservedCount() const { return m_allocCount; } - size_t byteSize() const { return m_allocCount * sizeof( T ); } - - private: - size_t m_count = 0; - size_t m_allocCount = 0; - T* m_ptr = nullptr; -}; -} // namespace - -void Scene::buildMeshAccels( uint32_t triangle_input_flags ) -{ - // Problem: - // The memory requirements of a compacted GAS are unknown prior to building the GAS. - // Hence, compaction of a GAS requires to build the GAS first and allocating memory for the compacted GAS afterwards. - // This causes a device-host synchronization point, potentially harming performance. - // This is most likely the case for small GASes where the actual building and compaction of the GAS is very fast. - // A naive algorithm processes one GAS at a time with the following steps: - // 1. compute memory sizes for the build process (temporary buffer size and build buffer size) - // 2. allocate temporary and build buffer - // 3. build the GAS (with temporary and build buffer) and compute the compacted size - // If compacted size is smaller than build buffer size (i.e., compaction is worth it): - // 4. allocate compacted buffer (final output buffer) - // 5. compact GAS from build buffer into compact buffer - // - // Idea of the algorithm: - // Batch process the building and compaction of multiple GASes to avoid host-device synchronization. - // Ideally, the number of synchronization points would be linear with the number of batches rather than the number of GASes. - // The main constraints for selecting batches of GASes are: - // a) the peak memory consumption when batch processing GASes, and - // b) the amount of memory for the output buffer(s), containing the compacted GASes. This is also part of a), but is also important after the build process. - // For the latter we try to keep it as minimal as possible, i.e., the total memory requirements for the output should equal the sum of the compacted sizes of the GASes. - // Hence, it should be avoided to waste memory by allocating buffers that are bigger than what is required for a compacted GAS. - // - // The peak memory consumption effectively defines the efficiency of the algorithm. - // If memory was unlimited, compaction isn't needed at all. - // A lower bound for the peak memory consumption during the build is the output of the process, the size of the compacted GASes. - // Peak memory consumption effectively defines the memory pool available during the batch building and compaction of GASes. - // - // The algorithm estimates the size of the compacted GASes by a give compaction ratio as well as the computed build size of each GAS. - // The compaction ratio is defined as: size of compacted GAS / size of build output of GAS. - // The validity of this estimate therefore depends on the assumed compaction ratio. - // The current algorithm assumes a fixed compaction ratio. - // Other strategies could be: - // - update the compaction ration on the fly by do statistics on the already processed GASes to have a better guess for the remaining batches - // - multiple compaction rations by type of GAS (e.g., motion vs static), since the type of GAS impacts the compaction ratio - // Further, compaction may be skipped for GASes that do not benefit from compaction (compaction ratio of 1.0). - // - // Before selecting GASes for a batch, all GASes are sorted by size (their build size). - // Big GASes are handled before smaller GASes as this will increase the likelihood of the peak memory consumption staying close to the minimal memory consumption. - // This also increase the benefit of batching since small GASes that benefit most from avoiding synchronizations are built "together". - // The minimum batch size is one GAS to ensure forward process. - // - // Goal: - // Estimate the required output size (the minimal peak memory consumption) and work within these bounds. - // Batch process GASes as long as they are expected to fit into the memory bounds (non strict). - // - // Assumptions: - // The inputs to each GAS are already in device memory and are needed afterwards. - // Otherwise this could be factored into the peak memory consumption. - // E.g., by uploading the input data to the device only just before building the GAS and releasing it right afterwards. - // - // Further, the peak memory consumption of the application / system is influenced by many factors unknown to this algorithm. - // E.g., if it is known that a big pool of memory is needed after GAS building anyways (e.g., textures that need to be present on the device), - // peak memory consumption will be higher eventually and the GAS build process could already make use of a bigger memory pool. - // - // TODOs: - // - compaction ratio estimation / updating - // - handling of non-compactable GASes - // - integration of GAS input data upload / freeing - // - add optional hard limits / check for hard memory limits (shrink batch size / abort, ...) - ////////////////////////////////////////////////////////////////////////// - - // Magic constants: - - // see explanation above - constexpr double initialCompactionRatio = 0.5; - - // It is assumed that trace is called later when the GASes are still in memory. - // We know that the memory consumption at that time will at least be the compacted GASes + some CUDA stack space. - // Add a "random" 250MB that we can use here, roughly matching CUDA stack space requirements. - constexpr size_t additionalAvailableMemory = 250 * 1024 * 1024; - - ////////////////////////////////////////////////////////////////////////// - - OptixAccelBuildOptions accel_options = {}; - accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION; - accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; - - struct GASInfo { - std::vector buildInputs; - OptixAccelBufferSizes gas_buffer_sizes; - std::shared_ptr mesh; - }; - std::multimap gases; - size_t totalTempOutputSize = 0; - - for(size_t i=0; iindices.size(); - std::vector buildInputs(num_subMeshes); - - assert(mesh->positions.size() == num_subMeshes && - mesh->normals.size() == num_subMeshes && - mesh->texcoords.size() == num_subMeshes); - - for(size_t j = 0; j < num_subMeshes; ++j) - { - OptixBuildInput& triangle_input = buildInputs[j]; - memset(&triangle_input, 0, sizeof(OptixBuildInput)); - triangle_input.type = OPTIX_BUILD_INPUT_TYPE_TRIANGLES; - triangle_input.triangleArray.vertexFormat = OPTIX_VERTEX_FORMAT_FLOAT3; - triangle_input.triangleArray.vertexStrideInBytes = - mesh->positions[j].byte_stride ? - mesh->positions[j].byte_stride : - sizeof(float3), - triangle_input.triangleArray.numVertices = mesh->positions[j].count; - triangle_input.triangleArray.vertexBuffers = &(mesh->positions[j].data); - triangle_input.triangleArray.indexFormat = - mesh->indices[j].elmt_byte_size == 2 ? - OPTIX_INDICES_FORMAT_UNSIGNED_SHORT3 : - OPTIX_INDICES_FORMAT_UNSIGNED_INT3; - triangle_input.triangleArray.indexStrideInBytes = - mesh->indices[j].byte_stride ? - mesh->indices[j].byte_stride : - mesh->indices[j].elmt_byte_size*3; - triangle_input.triangleArray.numIndexTriplets = mesh->indices[j].count / 3; - triangle_input.triangleArray.indexBuffer = mesh->indices[j].data; - triangle_input.triangleArray.flags = &triangle_input_flags; - triangle_input.triangleArray.numSbtRecords = 1; - } - - OptixAccelBufferSizes gas_buffer_sizes; - OPTIX_CHECK( optixAccelComputeMemoryUsage( m_context, &accel_options, buildInputs.data(), - static_cast( num_subMeshes ), &gas_buffer_sizes ) ); - - totalTempOutputSize += gas_buffer_sizes.outputSizeInBytes; - GASInfo g = {std::move( buildInputs ), gas_buffer_sizes, mesh}; - gases.emplace( gas_buffer_sizes.outputSizeInBytes, g ); - } - - size_t totalTempOutputProcessedSize = 0; - size_t usedCompactedOutputSize = 0; - double compactionRatio = initialCompactionRatio; - - CuBuffer d_temp; - CuBuffer d_temp_output; - CuBuffer d_temp_compactedSizes; - - OptixAccelEmitDesc emitProperty = {}; - emitProperty.type = OPTIX_PROPERTY_TYPE_COMPACTED_SIZE; - - while( !gases.empty() ) - { - // The estimated total output size that we end up with when using compaction. - // It defines the minimum peak memory consumption, but is unknown before actually building all GASes. - // Working only within these memory constraints results in an actual peak memory consumption that is very close to the minimal peak memory consumption. - size_t remainingEstimatedTotalOutputSize = - ( size_t )( ( totalTempOutputSize - totalTempOutputProcessedSize ) * compactionRatio ); - size_t availableMemPoolSize = remainingEstimatedTotalOutputSize + additionalAvailableMemory; - // We need to fit the following things into availableMemPoolSize: - // - temporary buffer for building a GAS (only during build, can be cleared before compaction) - // - build output buffer of a GAS - // - size (actual number) of a compacted GAS as output of a build - // - compacted GAS - - size_t batchNGASes = 0; - size_t batchBuildOutputRequirement = 0; - size_t batchBuildMaxTempRequirement = 0; - size_t batchBuildCompactedRequirement = 0; - for( auto it = gases.rbegin(); it != gases.rend(); it++ ) - { - batchBuildOutputRequirement += it->second.gas_buffer_sizes.outputSizeInBytes; - batchBuildCompactedRequirement += ( size_t )( it->second.gas_buffer_sizes.outputSizeInBytes * compactionRatio ); - // roughly account for the storage of the compacted size, although that goes into a separate buffer - batchBuildOutputRequirement += 8ull; - // make sure that all further output pointers are 256 byte aligned - batchBuildOutputRequirement = roundUp( batchBuildOutputRequirement, 256ull ); - // temp buffer is shared for all builds in the batch - batchBuildMaxTempRequirement = std::max( batchBuildMaxTempRequirement, it->second.gas_buffer_sizes.tempSizeInBytes ); - batchNGASes++; - if( ( batchBuildOutputRequirement + batchBuildMaxTempRequirement + batchBuildCompactedRequirement ) > availableMemPoolSize ) - break; - } - - // d_temp may still be available from a previous batch, but is freed later if it is "too big" - d_temp.allocIfRequired( batchBuildMaxTempRequirement ); - - // trash existing buffer if it is more than 10% bigger than what we need - // if it is roughly the same, we keep it - if( d_temp_output.byteSize() > batchBuildOutputRequirement * 1.1 ) - d_temp_output.free(); - d_temp_output.allocIfRequired( batchBuildOutputRequirement ); - - // this buffer is assumed to be very small - // trash d_temp_compactedSizes if it is at least 20MB in size and at least double the size than required for the next run - if( d_temp_compactedSizes.reservedCount() > batchNGASes * 2 && d_temp_compactedSizes.byteSize() > 20 * 1024 * 1024 ) - d_temp_compactedSizes.free(); - d_temp_compactedSizes.allocIfRequired( batchNGASes ); - - auto it = gases.rbegin(); - for( size_t i = 0, tempOutputAlignmentOffset = 0; i < batchNGASes; ++i ) - { - emitProperty.result = d_temp_compactedSizes.get( i ); - GASInfo& info = it->second; - - OPTIX_CHECK( optixAccelBuild( m_context, 0, // CUDA stream - &accel_options, - info.buildInputs.data(), - static_cast( info.buildInputs.size() ), - d_temp.get(), - d_temp.byteSize(), - d_temp_output.get( tempOutputAlignmentOffset ), - info.gas_buffer_sizes.outputSizeInBytes, - &info.mesh->gas_handle, - &emitProperty, // emitted property list - 1 // num emitted properties - ) ); - - tempOutputAlignmentOffset += roundUp( info.gas_buffer_sizes.outputSizeInBytes, 256ull ); - it++; - } - - // trash d_temp if it is at least 20MB in size - if( d_temp.byteSize() > 20 * 1024 * 1024 ) - d_temp.free(); - - // download all compacted sizes to allocate final output buffers for these GASes - std::vector h_compactedSizes( batchNGASes ); - d_temp_compactedSizes.download( h_compactedSizes.data() ); - - ////////////////////////////////////////////////////////////////////////// - // TODO: - // Now we know the actual memory requirement of the compacted GASes. - // Based on that we could shrink the batch if the compaction ratio is bad and we need to strictly fit into the/any available memory pool. - bool canCompact = false; - it = gases.rbegin(); - for( size_t i = 0; i < batchNGASes; ++i ) - { - GASInfo& info = it->second; - if( info.gas_buffer_sizes.outputSizeInBytes > h_compactedSizes[i] ) - { - canCompact = true; - break; - } - it++; - } - - // sum of size of compacted GASes - size_t batchCompactedSize = 0; - - if( canCompact ) - { - ////////////////////////////////////////////////////////////////////////// - // "batch allocate" the compacted buffers - it = gases.rbegin(); - for( size_t i = 0; i < batchNGASes; ++i ) - { - GASInfo& info = it->second; - batchCompactedSize += h_compactedSizes[i]; - CUDA_CHECK( cudaMalloc( reinterpret_cast( &info.mesh->d_gas_output ), h_compactedSizes[i] ) ); - totalTempOutputProcessedSize += info.gas_buffer_sizes.outputSizeInBytes; - it++; - } - - it = gases.rbegin(); - for( size_t i = 0; i < batchNGASes; ++i ) - { - GASInfo& info = it->second; - OPTIX_CHECK( optixAccelCompact( m_context, 0, info.mesh->gas_handle, info.mesh->d_gas_output, - h_compactedSizes[i], &info.mesh->gas_handle ) ); - it++; - } - } - else - { - it = gases.rbegin(); - for( size_t i = 0, tempOutputAlignmentOffset = 0; i < batchNGASes; ++i ) - { - GASInfo& info = it->second; - info.mesh->d_gas_output = d_temp_output.get( tempOutputAlignmentOffset ); - batchCompactedSize += h_compactedSizes[i]; - totalTempOutputProcessedSize += info.gas_buffer_sizes.outputSizeInBytes; - - tempOutputAlignmentOffset += roundUp( info.gas_buffer_sizes.outputSizeInBytes, 256ull ); - it++; - } - d_temp_output.release(); - } - - usedCompactedOutputSize += batchCompactedSize; - - gases.erase( it.base(), gases.end() ); - } -} - - -///TODO -struct Instance -{ - float transform[12]; -}; - -void Scene::buildInstanceAccel( int rayTypeCount ) -{ - const size_t num_instances = m_meshes.size(); - - std::vector optix_instances( num_instances ); - - unsigned int sbt_offset = 0; - for( size_t i = 0; i < m_meshes.size(); ++i ) - { - auto mesh = m_meshes[i]; - auto& optix_instance = optix_instances[i]; - memset( &optix_instance, 0, sizeof( OptixInstance ) ); - - optix_instance.flags = OPTIX_INSTANCE_FLAG_NONE; - optix_instance.instanceId = static_cast( i ); - optix_instance.sbtOffset = sbt_offset; - optix_instance.visibilityMask = 1; - optix_instance.traversableHandle = mesh->gas_handle; - memcpy( optix_instance.transform, mesh->transform.getData(), sizeof( float ) * 12 ); - - sbt_offset += static_cast( mesh->indices.size() ) * rayTypeCount; // one sbt record per GAS build input per RAY_TYPE - } - - const size_t instances_size_in_bytes = sizeof( OptixInstance ) * num_instances; - CUdeviceptr d_instances; - CUDA_CHECK( cudaMalloc( reinterpret_cast( &d_instances ), instances_size_in_bytes ) ); - CUDA_CHECK( cudaMemcpy( - reinterpret_cast( d_instances ), - optix_instances.data(), - instances_size_in_bytes, - cudaMemcpyHostToDevice - ) ); - - OptixBuildInput instance_input = {}; - instance_input.type = OPTIX_BUILD_INPUT_TYPE_INSTANCES; - instance_input.instanceArray.instances = d_instances; - instance_input.instanceArray.numInstances = static_cast( num_instances ); - - OptixAccelBuildOptions accel_options = {}; - accel_options.buildFlags = OPTIX_BUILD_FLAG_NONE; - accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; - - OptixAccelBufferSizes ias_buffer_sizes; - OPTIX_CHECK( optixAccelComputeMemoryUsage( - m_context, - &accel_options, - &instance_input, - 1, // num build inputs - &ias_buffer_sizes - ) ); - - CUdeviceptr d_temp_buffer; - CUDA_CHECK( cudaMalloc( - reinterpret_cast( &d_temp_buffer ), - ias_buffer_sizes.tempSizeInBytes - ) ); - CUDA_CHECK( cudaMalloc( - reinterpret_cast( &m_d_ias_output_buffer ), - ias_buffer_sizes.outputSizeInBytes - ) ); - - OPTIX_CHECK( optixAccelBuild( - m_context, - nullptr, // CUDA stream - &accel_options, - &instance_input, - 1, // num build inputs - d_temp_buffer, - ias_buffer_sizes.tempSizeInBytes, - m_d_ias_output_buffer, - ias_buffer_sizes.outputSizeInBytes, - &m_ias_handle, - nullptr, // emitted property list - 0 // num emitted properties - ) ); - - CUDA_CHECK( cudaFree( reinterpret_cast( d_temp_buffer ) ) ); - CUDA_CHECK( cudaFree( reinterpret_cast( d_instances ) ) ); -} - -void Scene::createPTXModule() -{ - - OptixModuleCompileOptions module_compile_options = {}; - module_compile_options.optLevel = OPTIX_COMPILE_OPTIMIZATION_DEFAULT; - module_compile_options.debugLevel = OPTIX_COMPILE_DEBUG_LEVEL_MINIMAL; - - m_pipeline_compile_options = {}; - m_pipeline_compile_options.usesMotionBlur = false; - m_pipeline_compile_options.traversableGraphFlags = OPTIX_TRAVERSABLE_GRAPH_FLAG_ALLOW_SINGLE_LEVEL_INSTANCING; - m_pipeline_compile_options.numPayloadValues = whitted::NUM_PAYLOAD_VALUES; - m_pipeline_compile_options.numAttributeValues = 2; // TODO - m_pipeline_compile_options.exceptionFlags = OPTIX_EXCEPTION_FLAG_NONE; // should be OPTIX_EXCEPTION_FLAG_STACK_OVERFLOW; - m_pipeline_compile_options.pipelineLaunchParamsVariableName = "params"; - - size_t inputSize = 0; - bool is_success; - const char* input = sutil::getInputData( nullptr, nullptr, "whitted.cu", "whitted.cu", inputSize, is_success); - - m_ptx_module = {}; - char log[2048]; - size_t sizeof_log = sizeof( log ); - OPTIX_CHECK_LOG( optixModuleCreateFromPTX( - m_context, - &module_compile_options, - &m_pipeline_compile_options, - input, - inputSize, - log, - &sizeof_log, - &m_ptx_module - ) ); -} - - -void Scene::createProgramGroups() -{ - OptixProgramGroupOptions program_group_options = {}; - - char log[2048]; - size_t sizeof_log = sizeof( log ); - - // - // Ray generation - // - { - - OptixProgramGroupDesc raygen_prog_group_desc = {}; - raygen_prog_group_desc.kind = OPTIX_PROGRAM_GROUP_KIND_RAYGEN; - raygen_prog_group_desc.raygen.module = m_ptx_module; - raygen_prog_group_desc.raygen.entryFunctionName = "__raygen__pinhole"; - - OPTIX_CHECK_LOG( optixProgramGroupCreate( - m_context, - &raygen_prog_group_desc, - 1, // num program groups - &program_group_options, - log, - &sizeof_log, - &m_raygen_prog_group - ) - ); - } - - // - // Miss - // - { - OptixProgramGroupDesc miss_prog_group_desc = {}; - miss_prog_group_desc.kind = OPTIX_PROGRAM_GROUP_KIND_MISS; - miss_prog_group_desc.miss.module = m_ptx_module; - miss_prog_group_desc.miss.entryFunctionName = "__miss__constant_radiance"; - sizeof_log = sizeof( log ); - OPTIX_CHECK_LOG( optixProgramGroupCreate( - m_context, - &miss_prog_group_desc, - 1, // num program groups - &program_group_options, - log, - &sizeof_log, - &m_radiance_miss_group - ) - ); - - memset( &miss_prog_group_desc, 0, sizeof( OptixProgramGroupDesc ) ); - miss_prog_group_desc.kind = OPTIX_PROGRAM_GROUP_KIND_MISS; - miss_prog_group_desc.miss.module = nullptr; // NULL miss program for occlusion rays - miss_prog_group_desc.miss.entryFunctionName = nullptr; - sizeof_log = sizeof( log ); - OPTIX_CHECK_LOG( optixProgramGroupCreate( - m_context, - &miss_prog_group_desc, - 1, // num program groups - &program_group_options, - log, - &sizeof_log, - &m_occlusion_miss_group - ) - ); - } - - // - // Hit group - // - { - OptixProgramGroupDesc hit_prog_group_desc = {}; - hit_prog_group_desc.kind = OPTIX_PROGRAM_GROUP_KIND_HITGROUP; - hit_prog_group_desc.hitgroup.moduleCH = m_ptx_module; - hit_prog_group_desc.hitgroup.entryFunctionNameCH = "__closesthit__radiance"; - sizeof_log = sizeof( log ); - OPTIX_CHECK_LOG( optixProgramGroupCreate( - m_context, - &hit_prog_group_desc, - 1, // num program groups - &program_group_options, - log, - &sizeof_log, - &m_radiance_hit_group - ) - ); - - memset( &hit_prog_group_desc, 0, sizeof( OptixProgramGroupDesc ) ); - hit_prog_group_desc.kind = OPTIX_PROGRAM_GROUP_KIND_HITGROUP; - hit_prog_group_desc.hitgroup.moduleCH = m_ptx_module; - hit_prog_group_desc.hitgroup.entryFunctionNameCH = "__closesthit__occlusion"; - sizeof_log = sizeof( log ); - OPTIX_CHECK( optixProgramGroupCreate( - m_context, - &hit_prog_group_desc, - 1, // num program groups - &program_group_options, - log, - &sizeof_log, - &m_occlusion_hit_group - ) - ); - } -} - - -void Scene::createPipeline() -{ - OptixProgramGroup program_groups[] = - { - m_raygen_prog_group, - m_radiance_miss_group, - m_occlusion_miss_group, - m_radiance_hit_group, - m_occlusion_hit_group - }; - - OptixPipelineLinkOptions pipeline_link_options = {}; - pipeline_link_options.maxTraceDepth = 2; - pipeline_link_options.debugLevel = OPTIX_COMPILE_DEBUG_LEVEL_FULL; - - char log[2048]; - size_t sizeof_log = sizeof( log ); - OPTIX_CHECK_LOG( optixPipelineCreate( - m_context, - &m_pipeline_compile_options, - &pipeline_link_options, - program_groups, - sizeof( program_groups ) / sizeof( program_groups[0] ), - log, - &sizeof_log, - &m_pipeline - ) ); -} - - -void Scene::createSBT() -{ - { - const size_t raygen_record_size = sizeof( EmptyRecord ); - CUDA_CHECK( cudaMalloc( reinterpret_cast( &m_sbt.raygenRecord ), raygen_record_size ) ); - - EmptyRecord rg_sbt; - OPTIX_CHECK( optixSbtRecordPackHeader( m_raygen_prog_group, &rg_sbt ) ); - CUDA_CHECK( cudaMemcpy( - reinterpret_cast( m_sbt.raygenRecord ), - &rg_sbt, - raygen_record_size, - cudaMemcpyHostToDevice - ) ); - } - - { - const size_t miss_record_size = sizeof( EmptyRecord ); - CUDA_CHECK( cudaMalloc( - reinterpret_cast( &m_sbt.missRecordBase ), - miss_record_size*whitted::RAY_TYPE_COUNT - ) ); - - EmptyRecord ms_sbt[ whitted::RAY_TYPE_COUNT ]; - OPTIX_CHECK( optixSbtRecordPackHeader( m_radiance_miss_group, &ms_sbt[0] ) ); - OPTIX_CHECK( optixSbtRecordPackHeader( m_occlusion_miss_group, &ms_sbt[1] ) ); - - CUDA_CHECK( cudaMemcpy( - reinterpret_cast( m_sbt.missRecordBase ), - ms_sbt, - miss_record_size*whitted::RAY_TYPE_COUNT, - cudaMemcpyHostToDevice - ) ); - m_sbt.missRecordStrideInBytes = static_cast( miss_record_size ); - m_sbt.missRecordCount = whitted::RAY_TYPE_COUNT; - } - - { - std::vector hitgroup_records; - for( const auto mesh : m_meshes ) - { - for( size_t i = 0; i < mesh->material_idx.size(); ++i ) - { - HitGroupRecord rec = {}; - OPTIX_CHECK( optixSbtRecordPackHeader( m_radiance_hit_group, &rec ) ); - rec.data.geometry_data.type = GeometryData::TRIANGLE_MESH; - rec.data.geometry_data.triangle_mesh.positions = mesh->positions[i]; - rec.data.geometry_data.triangle_mesh.normals = mesh->normals[i]; - rec.data.geometry_data.triangle_mesh.texcoords = mesh->texcoords[i]; - rec.data.geometry_data.triangle_mesh.indices = mesh->indices[i]; - - const int32_t mat_idx = mesh->material_idx[i]; - if( mat_idx >= 0 ) - rec.data.material_data.pbr = m_materials[ mat_idx ]; - else - rec.data.material_data.pbr = MaterialData::Pbr(); - hitgroup_records.push_back( rec ); - - OPTIX_CHECK( optixSbtRecordPackHeader( m_occlusion_hit_group, &rec ) ); - hitgroup_records.push_back( rec ); - } - } - - const size_t hitgroup_record_size = sizeof( HitGroupRecord ); - CUDA_CHECK( cudaMalloc( - reinterpret_cast( &m_sbt.hitgroupRecordBase ), - hitgroup_record_size*hitgroup_records.size() - ) ); - CUDA_CHECK( cudaMemcpy( - reinterpret_cast( m_sbt.hitgroupRecordBase ), - hitgroup_records.data(), - hitgroup_record_size*hitgroup_records.size(), - cudaMemcpyHostToDevice - ) ); - - m_sbt.hitgroupRecordStrideInBytes = static_cast( hitgroup_record_size ); - m_sbt.hitgroupRecordCount = static_cast( hitgroup_records.size() ); - } -} - -} // namespace sutil diff --git a/zenovis/xinxinoptix/SDK/sutil/Scene.h b/zenovis/xinxinoptix/SDK/sutil/Scene.h deleted file mode 100644 index 998257f4c7..0000000000 --- a/zenovis/xinxinoptix/SDK/sutil/Scene.h +++ /dev/null @@ -1,151 +0,0 @@ -// -// Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of NVIDIA CORPORATION nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include - - -namespace sutil -{ - - -class Scene -{ -public: - SUTILAPI Scene(); - SUTILAPI ~Scene(); - struct MeshGroup - { - std::string name; - Matrix4x4 transform; - - std::vector indices; - std::vector > positions; - std::vector > normals; - std::vector > texcoords; - - std::vector material_idx; - - OptixTraversableHandle gas_handle = 0; - CUdeviceptr d_gas_output = 0; - - Aabb object_aabb; - Aabb world_aabb; - }; - - - SUTILAPI void addCamera ( const Camera& camera ) { m_cameras.push_back( camera ); } - SUTILAPI void addMesh ( std::shared_ptr mesh ) { m_meshes.push_back( mesh ); } - SUTILAPI void addMaterial( const MaterialData::Pbr& mtl ) { m_materials.push_back( mtl ); } - SUTILAPI void addBuffer ( const uint64_t buf_size, const void* data ); - SUTILAPI void addImage( - const int32_t width, - const int32_t height, - const int32_t bits_per_component, - const int32_t num_components, - const void* data - ); - SUTILAPI void addSampler( - cudaTextureAddressMode address_s, - cudaTextureAddressMode address_t, - cudaTextureFilterMode filter_mode, - const int32_t image_idx - ); - - SUTILAPI CUdeviceptr getBuffer ( int32_t buffer_index )const; - SUTILAPI cudaArray_t getImage ( int32_t image_index )const; - SUTILAPI cudaTextureObject_t getSampler( int32_t sampler_index )const; - - SUTILAPI void finalize(); - SUTILAPI void cleanup(); - - SUTILAPI Camera camera()const; - SUTILAPI OptixPipeline pipeline()const { return m_pipeline; } - SUTILAPI const OptixShaderBindingTable* sbt()const { return &m_sbt; } - SUTILAPI OptixTraversableHandle traversableHandle() const { return m_ias_handle; } - SUTILAPI sutil::Aabb aabb() const { return m_scene_aabb; } - SUTILAPI OptixDeviceContext context() const { return m_context; } - SUTILAPI const std::vector& materials() const { return m_materials; } - SUTILAPI const std::vector>& meshes() const { return m_meshes; } - - SUTILAPI void createContext(); - SUTILAPI void buildMeshAccels( uint32_t triangle_input_flags = OPTIX_GEOMETRY_FLAG_DISABLE_ANYHIT ); - SUTILAPI void buildInstanceAccel( int rayTypeCount = whitted::RAY_TYPE_COUNT ); - -private: - void createPTXModule(); - void createProgramGroups(); - void createPipeline(); - void createSBT(); - - // TODO: custom geometry support - - std::vector m_cameras; - std::vector > m_meshes; - std::vector m_materials; - std::vector m_buffers; - std::vector m_samplers; - std::vector m_images; - sutil::Aabb m_scene_aabb; - - OptixDeviceContext m_context = 0; - OptixShaderBindingTable m_sbt = {}; - OptixPipelineCompileOptions m_pipeline_compile_options = {}; - OptixPipeline m_pipeline = 0; - OptixModule m_ptx_module = 0; - - OptixProgramGroup m_raygen_prog_group = 0; - OptixProgramGroup m_radiance_miss_group = 0; - OptixProgramGroup m_occlusion_miss_group = 0; - OptixProgramGroup m_radiance_hit_group = 0; - OptixProgramGroup m_occlusion_hit_group = 0; - OptixTraversableHandle m_ias_handle = 0; - CUdeviceptr m_d_ias_output_buffer = 0; -}; - - -SUTILAPI void loadScene( const std::string& filename, Scene& scene ); - -} // end namespace sutil - diff --git a/zenovis/xinxinoptix/Sampling.h b/zenovis/xinxinoptix/Sampling.h new file mode 100644 index 0000000000..76358988a7 --- /dev/null +++ b/zenovis/xinxinoptix/Sampling.h @@ -0,0 +1,179 @@ +#pragma once +#include +#include + +#include +#include + +#ifdef __CUDACC_RTC__ + #include "zxxglslvec.h" + using Vector3f = vec3; +#else + #include "Host.h" + #include + using Vector3f = zeno::vec<3, float>; +#endif + +#ifdef __CUDACC_DEBUG__ + #define DCHECK assert +#else + +#define DCHECK(x) \ + do { \ + } while (false) /* swallow semicolon */ + +#endif + +namespace pbrt { + +template +inline float Sqr(T v) { return v * v; } + +inline float SafeASin(float x) { + DCHECK(x >= -1.0001 && x <= 1.0001); + return asinf(clamp(x, -1.0f, 1.0f)); +} + inline float SafeACos(float x) { + DCHECK(x >= -1.0001 && x <= 1.0001); + return acosf(clamp(x, -1.0f, 1.0f)); +} + +inline float SafeSqrt(float x) { + DCHECK(x > -1e-3f); // not too negative + return sqrtf(fmaxf(0.f, x)); +} + +inline float AbsDot(Vector3f v, Vector3f n) { + return abs(dot(v, n)); +} + +inline float AngleBetween(Vector3f v1, Vector3f v2) { + if (dot(v1, v2) < 0) + return M_PIf - 2 * SafeASin(length(v1 + v2) / 2); + else + return 2 * SafeASin(length(v2 - v1) / 2); +} + +inline float Radians(float deg) { + return (M_PIf / 180) * deg; +} + +inline float Degrees(float rad) { + return (180 / M_PIf) * rad; +} + +inline void CoordinateSystem(const float3& v1, float3 *v2, float3 *v3) { + + float _sign_ = copysignf(float(1), v1.z); + float a = -1 / (_sign_ + v1.z); + float b = v1.x * v1.y * a; + *v2 = make_float3(1 + _sign_ * Sqr(v1.x) * a, _sign_ * b, -_sign_ * v1.x); + *v3 = make_float3(b, _sign_ + Sqr(v1.y) * a, -v1.y); + + normalize(*v2); + normalize(*v3); +} + +inline void CoordinateSystem(const float3& a, float3& b, float3& c) { + +// if (fabsf(a.x) > fabsf(a.y)) +// b = float3{-a.z, 0, a.x} / +// sqrtf(fmaxf(__FLT_DENORM_MIN__, a.x * a.x + a.z * a.z)); +// else +// b = float3{0, a.z, -a.y} / +// sqrtf(fmaxf(__FLT_DENORM_MIN__, a.y * a.y + a.z * a.z)); + + if (fabs(a.x) > fabs(a.y)) + b = float3{-a.z, 0, a.x}; + else + b = float3{0, a.z, -a.y}; + + b = normalize(b); + c = cross(a, b); +} + +inline float3 SphericalDirection(float sinTheta, float cosTheta, float phi) { + return make_float3(sinTheta * cosf(phi), sinTheta * sinf(phi), cosTheta); +} + +inline float3 SphericalDirection(float sinTheta, float cosTheta, float phi, + const float3 &x, const float3 &y, const float3 &z) { + return sinTheta * cosf(phi) * x + sinTheta * sinf(phi) * y + cosTheta * z; +} + + inline float3 UniformSampleSphere(const float2 &uu) { + float z = 1 - 2 * uu.x; + float r = sqrtf(fmaxf(0.0f, 1.0f - z * z)); + float phi = 2 * M_PIf * uu.y; + return make_float3(r * cosf(phi), r * sinf(phi), z); +} + +} // namespace pbrt + + +namespace rtgems { + + constexpr float origin() { return 1.0f / 16.0f; } + constexpr float int_scale() { return 3.0f * 256.0f; } + constexpr float float_scale() { return 3.0f / 65536.0f; } + + // Normal points outward for rays exiting the surface, else is flipped. + static __inline__ __device__ float3 offset_ray(const float3 p, const float3 n) + { + int3 of_i { + (int)(int_scale() * n.x), + (int)(int_scale() * n.y), + (int)(int_scale() * n.z) }; + + float3 p_i { + __int_as_float(__float_as_int(p.x) + ((p.x < 0) ? -of_i.x : of_i.x)), + __int_as_float(__float_as_int(p.y) + ((p.y < 0) ? -of_i.y : of_i.y)), + __int_as_float(__float_as_int(p.z) + ((p.z < 0) ? -of_i.z : of_i.z)) }; + + return float3{ + fabsf(p.x) < origin() ? p.x+float_scale()*n.x : p_i.x, + fabsf(p.y) < origin() ? p.y+float_scale()*n.y : p_i.y, + fabsf(p.z) < origin() ? p.z+float_scale()*n.z : p_i.z }; + } +} + +// *Really* minimal PCG32 code / (c) 2014 M.E. O'Neill / pcg-random.org +// Licensed under Apache License 2.0 (NO WARRANTY, etc. see website) + +// typedef struct { uint64_t state; uint64_t inc; } pcg32_random_t; + +// inline uint32_t pcg32_random_r(pcg32_random_t* rng) +// { +// uint64_t oldstate = rng->state; +// // Advance internal state +// rng->state = oldstate * 6364136223846793005ULL + (rng->inc|1); +// // Calculate output function (XSH RR), uses old state for max ILP +// uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u; +// uint32_t rot = oldstate >> 59u; +// return (xorshifted >> rot) | (xorshifted << ((-rot) & 31)); +// } + +//https://www.reedbeta.com/blog/hash-functions-for-gpu-rendering/ +static __host__ __device__ __inline__ uint32_t pcg_hash(uint32_t &seed ) +{ + auto state = seed * 747796405u + 2891336453u; + auto word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; + return (word >> 22u) ^ word; +} + +static __host__ __device__ __inline__ uint32_t pcg_rng(uint32_t &seed) +{ + auto state = seed; + seed = seed * 747796405u + 2891336453u; + auto word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; + return (word >> 22u) ^ word; +} + +static inline uint32_t hash_iqnt2d(const uint32_t x, const uint32_t y) +{ + const uint32_t qx = 1103515245U * ((x >> 1U) ^ (y)); + const uint32_t qy = 1103515245U * ((y >> 1U) ^ (x)); + const uint32_t n = 1103515245U * ((qx) ^ (qy >> 3U)); + + return n; +} \ No newline at end of file diff --git a/zenovis/xinxinoptix/Shape.h b/zenovis/xinxinoptix/Shape.h new file mode 100644 index 0000000000..56e3e042f1 --- /dev/null +++ b/zenovis/xinxinoptix/Shape.h @@ -0,0 +1,426 @@ +#pragma once +#include +#include +#include + +#ifdef __CUDACC_RTC__ +#include "zxxglslvec.h" +#endif + +struct LightSampleRecord { + float3 p; + float PDF; + + float3 n; + float NoL; + + float3 dir; + float dist; + + float2 uv; + + float intensity = 1.0f; + bool isDelta = false; +}; + +struct PointShape { + float3 p; + + inline float PDF() {return 0.25f / M_PIf;} + + inline void SampleAsLight(LightSampleRecord* lsr, const float2& uu, const float3& shadingP) { + + auto vector = p - shadingP; + auto dist2 = dot(vector, vector); + auto dist = sqrtf(dist2); + + lsr->dist = dist; + lsr->dir = vector / dist; + lsr->p = p; + lsr->n = -lsr->dir; + + lsr->PDF = 1.0f; //PDF(); + lsr->NoL = 1.0f; + lsr->intensity = M_PIf / dist2; + lsr->isDelta = true; + } + + pbrt::LightBounds BoundAsLight(float phi, bool doubleSided) { + + float Phi = 4 * M_PIf * phi; + + auto& tmp = reinterpret_cast(p); + auto bounds = pbrt::Bounds3f{tmp, tmp}; + + return pbrt::LightBounds(bounds, Vector3f(0, 0, 1), + Phi, cosf(M_PIf), cosf(M_PIf / 2), false); + } +}; + +struct RectShape { + float3 v0, v1, v2; + float3 normal; + float area; + + inline float PDF() { + return 1.0f / area; + } + + inline void EvalAfterHit(LightSampleRecord* lsr, const float3& dir, const float& dist, const float3& shadingP) { + + float lightNoL = dot(-dir, normal); + float lightPDF = dist * dist * PDF() / lightNoL; + + lsr->p = shadingP + dir * dist; + lsr->n = normal; + lsr->dir = dir; + lsr->dist = dist; + + lsr->PDF = lightPDF; + lsr->NoL = lightNoL; + } + + inline void SampleAsLight(LightSampleRecord* lsr, const float2& uu, const float3& shadingP) { + + lsr->n = normalize(normal); + lsr->p = v0 + v1 * uu.x + v2 * uu.y; + + lsr->uv = uu; + + lsr->dir = (lsr->p - shadingP); + //lsr->dir = normalize(lsr->dir); + auto sign = copysignf(1.0f, dot(lsr->n, -lsr->dir)); + + lsr->p = rtgems::offset_ray(lsr->p, lsr->n * sign); + lsr->dir = lsr->p - shadingP; + lsr->dist = length(lsr->dir); + lsr->dir = lsr->dir / lsr->dist; + + lsr->NoL = dot(-lsr->dir, lsr->n); + lsr->PDF = 0.0f; + + if (fabsf(lsr->NoL) > __FLT_EPSILON__) { + lsr->PDF = lsr->dist * lsr->dist * PDF() / fabsf(lsr->NoL); + } + } + + inline bool hitAsLight(LightSampleRecord* lsr, const float3& ray_orig, const float3& ray_dir) { + + // assuming vectors are all normalized + float denom = dot(normal, -ray_dir); + if (denom <= __FLT_DENORM_MIN__) {return false;} + + float3 vector = ray_orig - v0; + float t = dot(normal, vector) / denom; + + if (t <= 0) { return false; } + + auto P = ray_orig + ray_dir * t; + auto delta = P - v0; + + auto v1v1 = dot(v1, v1); + auto q1 = dot(delta, v1); + if (q1<0.0f || q1>v1v1) {return false;} + + auto v2v2 = dot(v2, v2); + auto q2 = dot(delta, v2); + if (q2<0.0f || q2>v2v2) {return false;} + + lsr->dir = ray_dir; + lsr->dist = t; + + lsr->n = normal; + lsr->NoL = denom; + + lsr->p = P; + lsr->PDF = 1.0f; + + return true; + } + + pbrt::Bounds3f bounds() { + + auto pmax = v0; + auto pmin = v1; + + float3 tmp[3] = {v0+v1, v0+v2, v0+v1+v2}; + + for (int i=0; i<3; i++) { + pmax = fmaxf(pmax, tmp[i]); + pmin = fminf(pmin, tmp[i]); + } + + pbrt::Bounds3f result; + result.pMax = reinterpret_cast(pmax); + result.pMin = reinterpret_cast(pmin); + + return result; + } + + pbrt::LightBounds BoundAsLight(float phi, bool doubleSided) { + + auto& nnn = reinterpret_cast(normal); + auto dc = pbrt::DirectionCone(nnn); + + return pbrt::LightBounds(bounds(), nnn, phi * area, + dc.cosTheta, fmaxf(cosf(M_PIf / 2.0f), 0.0f), doubleSided); + } +}; + +struct ConeShape { + float3 p; + float range; + + float3 dir; + float cosFalloffStart; + float cosFalloffEnd; + + inline void sample(LightSampleRecord* lsr, const float2& uu, const float3& shadingP) { + auto vector = p - shadingP; + auto dist2 = dot(vector, vector); + auto dist = sqrtf(dist2); + + lsr->dir = vector / dist; + lsr->dist = dist; + + lsr->n = dir; + lsr->NoL = dot(lsr->dir, dir); + + lsr->p = p; + lsr->PDF = 1.0f; + + #ifdef __CUDACC_RTC__ + lsr->intensity = smoothstep(cosFalloffEnd, cosFalloffStart, lsr->NoL); + #endif + + lsr->intensity /= dist2; + } + + inline float Phi() { + return 2 * M_PIf * ((1.0f - cosFalloffStart) + (cosFalloffStart - cosFalloffEnd) / 2.0f); + } + + pbrt::LightBounds BoundAsLight(float phi, bool doubleSided) { + + auto Phi = M_PIf * 4 * phi; + + float cosTheta_e = cosf(acosf(cosFalloffEnd) - acosf(cosFalloffStart)); + // Allow a little slop here to deal with fp round-off error in the computation of + // cosTheta_p in the importance function. + if (cosTheta_e == 1 && cosFalloffEnd != cosFalloffStart) + cosTheta_e = 0.999f; + + auto& w = reinterpret_cast(dir); + auto& tmp = reinterpret_cast(p); + auto bounds = pbrt::Bounds3f{tmp, tmp}; + + return pbrt::LightBounds(bounds, w, Phi, cosFalloffStart, cosTheta_e, false); + } +}; + +struct SphereShape { + float3 center; + float radius; + float area; + + inline float PDF() { + return 1.0f / area; + } + + inline float PDF(const float3& shadingP, float dist2, float NoL) { + + if (dist2 < radius * radius) { + return dist2 / fabsf(NoL); + } + + float sinThetaMax2 = clamp( radius * radius / dist2, 0.0, 1.0); + + if (sinThetaMax2 <= __FLT_EPSILON__) { + return 1.0f; // point light + } + + float cosThetaMax = sqrtf( 1.0 - sinThetaMax2 ); + return 1.0f / ( 2.0f * M_PIf * (1.0 - cosThetaMax) ); + } + + inline bool hitAsLight(LightSampleRecord* lsr, const float3& ray_origin, const float3& ray_dir) { + + float3 f = ray_origin - center; + float b2 = dot(f, ray_dir); + if (b2 >= 0) { return false; } + + float r2 = radius * radius; + + float3 fd = f - b2 * ray_dir; + float discriminant = r2 - dot(fd, fd); + + if (discriminant >= 0.0f) + { + float c = dot(f, f) - r2; + float sqrtVal = sqrt(discriminant); + + // include Press, William H., Saul A. Teukolsky, William T. Vetterling, and Brian P. Flannery, + // "Numerical Recipes in C," Cambridge University Press, 1992. + float q = (b2 >= 0) ? -sqrtVal - b2 : sqrtVal - b2; + + lsr->dir = ray_dir; + lsr->dist = fminf(c/q, q); + lsr->p = ray_origin + ray_dir * lsr->dist; + // lsr->n = normalize(lsr->p - center); + // lsr->p = rtgems::offset_ray(lsr->p, lsr->n); + // lsr->dist = length(lsr->p - ray_origin); + return true; + + // we don't bother testing for division by zero + //ReportHit(c / q, 0, sphrAttr); + // more distant hit - not needed if we know we will intersect with the outside of the sphere + //ReportHit(q / a, 0, sphrAttr); + } + return false; + } + + inline void EvalAfterHit(LightSampleRecord* lsr, const float3& dir, const float& distance, const float3& shadingP) { + + auto vector = center - shadingP; + auto dist2 = dot(vector, vector); + auto dist = sqrtf(dist2); + + lsr->p = shadingP + dir * distance; + lsr->n = normalize(lsr->p - center); + if (dist2 < radius * radius) { + lsr->n *= -1; + } + + lsr->NoL = dot(lsr->n, -dir); + lsr->PDF = PDF(shadingP, dist2, lsr->NoL); + + lsr->dir = dir; + lsr->dist = distance; + } + + inline void SampleAsLight(LightSampleRecord* lsr, const float2& uu, const float3& shadingP) { + + float3 vector = center - shadingP; + float dist2 = dot(vector, vector); + float dist = sqrtf(dist2); + float3 dir = vector / dist; + + float radius2 = radius * radius; + + if (dist2 <= radius2) { // inside sphere + + auto localP = pbrt::UniformSampleSphere(uu); + auto worldP = center + localP * radius; + + auto localN = -localP; //facing center + auto worldN = localN; + + lsr->p = rtgems::offset_ray(worldP, worldN); + lsr->n = worldN; + + vector = lsr->p - shadingP; + dist2 = dot(vector, vector); + + if (dist2 == 0) { + lsr->PDF = 0.0f; return; + } + + dist = sqrtf(dist2); + dir = vector / dist; + + lsr->dist = dist; + lsr->dir = dir; + + lsr->NoL = dot(-dir, worldN); + lsr->PDF = lsr->dist * lsr->dist / lsr->NoL; + return; + } + + assert(dist > radius); + + // Sample sphere uniformly inside subtended cone + float invDc = 1.0f / dist; + float3& wc = dir; float3 wcX, wcY; + pbrt::CoordinateSystem(wc, wcX, wcY); + + // Compute $\theta$ and $\phi$ values for sample in cone + float sinThetaMax = radius * invDc; + const float sinThetaMax2 = sinThetaMax * sinThetaMax; + float invSinThetaMax = 1.0f / sinThetaMax; + + assert(sinThetaMax2 > 0); + const float cosThetaMax = sqrtf(1.0f - clamp(sinThetaMax2, 0.0f, 1.0f)); + + auto epsilon = 2e-3f; + + if (sinThetaMax < epsilon) { + + lsr->p = center - dir * radius; + lsr->p = rtgems::offset_ray(lsr->p, -dir); + + lsr->n = -dir; + lsr->dir = dir; + lsr->dist = length(lsr->p - shadingP); + + lsr->PDF = 1.0f; + lsr->NoL = 1.0f; + lsr->intensity = M_PIf * radius2 / (lsr->dist * lsr->dist); + lsr->isDelta = true; + return; + } // point light + + float cosTheta = (cosThetaMax - 1) * uu.x + 1; + float sinTheta2 = 1 - cosTheta * cosTheta; + + if (sinThetaMax2 < 0.00068523f /* sin^2(1.5 deg) */) { + /* Fall back to a Taylor series expansion for small angles, where + the standard approach suffers from severe cancellation errors */ + sinTheta2 = sinThetaMax2 * uu.x; + cosTheta = sqrtf(1 - sinTheta2); + } + + // Compute angle $\alpha$ from center of sphere to sampled point on surface + float cosAlpha = sinTheta2 * invSinThetaMax + + cosTheta * sqrtf(fmaxf(0.f, 1.f - sinTheta2 * invSinThetaMax * invSinThetaMax)); + float sinAlpha = sqrtf(fmaxf(0.f, 1.f - cosAlpha * cosAlpha)); + float phi = uu.y * 2 * M_PIf; + + // Compute surface normal and sampled point on sphere + float3 nWorld = pbrt::SphericalDirection(sinAlpha, cosAlpha, phi, -wcX, -wcY, -wc); + float3 pWorld = center + radius * nWorld; + + lsr->p = rtgems::offset_ray(pWorld, nWorld); + lsr->n = nWorld; + + vector = lsr->p - shadingP; + dist2 = dot(vector, vector); + dist = sqrtf(dist2); + dir = vector / dist; + + lsr->dist = dist; + lsr->dir = dir; + + lsr->PDF = 1.0f / (2.0f * M_PIf * (1.0f - cosThetaMax)); // Uniform cone PDF. + lsr->NoL = dot(-lsr->dir, lsr->n); + } + + pbrt::Bounds3f bounds() { + + auto pmax = center + make_float3(abs(radius)); + auto pmin = center - make_float3(abs(radius)); + + pbrt::Bounds3f result; + result.pMax = reinterpret_cast(pmax); + result.pMin = reinterpret_cast(pmin); + + return result; + } + + pbrt::LightBounds BoundAsLight(float phi, bool doubleSided) { + + auto dc = pbrt::DirectionCone::EntireSphere(); + + return pbrt::LightBounds(bounds(), dc.w, phi * area, + dc.cosTheta, fmaxf(cos(M_PIf / 2.0f), 0.0f), doubleSided); + } +}; \ No newline at end of file diff --git a/zenovis/xinxinoptix/TraceStuff.h b/zenovis/xinxinoptix/TraceStuff.h index 3350ea8fec..5c07413c59 100644 --- a/zenovis/xinxinoptix/TraceStuff.h +++ b/zenovis/xinxinoptix/TraceStuff.h @@ -1,14 +1,20 @@ #pragma once #include - +#include #include "zxxglslvec.h" #include "optixPathTracer.h" -#define _FLT_EPL_ 1.19209290e-7F +#include +#include +#include +#define _FLT_MAX_ __FLT_MAX__ +#define _FLT_MIN_ __FLT_MIN__ +#define _FLT_EPL_ __FLT_EPSILON__ -#define _FLT_MAX_ 3.40282347e+38F -#define _FLT_MIN_ 1.17549435e-38F +#ifndef __CUDACC_RTC__ +#include "Host.h" +#endif #ifndef uint using uint = unsigned int; @@ -25,7 +31,6 @@ static __forceinline__ __device__ void* unpackPointer( unsigned int i0, unsigned return ptr; } - static __forceinline__ __device__ void packPointer( void* ptr, unsigned int& i0, unsigned int& i1 ) { const unsigned long long uptr = reinterpret_cast( ptr ); @@ -33,32 +38,6 @@ static __forceinline__ __device__ void packPointer( void* ptr, unsigned int& i0 i1 = uptr & 0x00000000ffffffff; } -namespace rtgems { - - constexpr float origin() { return 1.0f / 32.0f; } - constexpr float int_scale() { return 256.0f; } - constexpr float float_scale() { return 1.0f / 65536.0f; } - - // Normal points outward for rays exiting the surface, else is flipped. - static __inline__ __device__ float3 offset_ray(const float3 p, const float3 n) - { - int3 of_i { - (int)(int_scale() * n.x), - (int)(int_scale() * n.y), - (int)(int_scale() * n.z) }; - - float3 p_i { - __int_as_float(__float_as_int(p.x) + ((p.x < 0) ? -of_i.x : of_i.x)), - __int_as_float(__float_as_int(p.y) + ((p.y < 0) ? -of_i.y : of_i.y)), - __int_as_float(__float_as_int(p.z) + ((p.z < 0) ? -of_i.z : of_i.z)) }; - - return float3{ - fabsf(p.x) < origin() ? p.x+float_scale()*n.x : p_i.x, - fabsf(p.y) < origin() ? p.y+float_scale()*n.y : p_i.y, - fabsf(p.z) < origin() ? p.z+float_scale()*n.z : p_i.z }; - } -} - enum medium{ vacum, isotropicScatter @@ -78,7 +57,6 @@ struct RadiancePRD float3 direction; float minSpecRough; bool passed; - bool next_ray_is_going_inside; float opacity; float prob; float prob2; @@ -99,8 +77,7 @@ struct RadiancePRD bool isSS; float scatterStep; int nonThinTransHit; - float3 LP; - float3 Ldir; + float Lweight; vec3 sigma_t_queue[8]; vec3 ss_alpha_queue[8]; @@ -108,12 +85,16 @@ struct RadiancePRD float samplePdf; bool fromDiff; + __forceinline__ float rndf() { + return rnd(this->seed); + //return (float)pcg_rng(this->seed) / (float)UINT_MAX; + } + unsigned char first_hit_type; vec3 extinction() { auto idx = clamp(curMatIdx, 0, 7); return sigma_t_queue[idx]; } - float CH; //cihou SS vec3 sigma_t; @@ -136,7 +117,7 @@ struct RadiancePRD bool origin_inside_vdb = false; bool surface_inside_vdb = false; - float trace_tmin = 0; + float _tmin_ = 0; float3 geometryNormal; void offsetRay() { @@ -154,7 +135,7 @@ struct RadiancePRD offsetRay(this->origin, new_dir); } - VisibilityMask _mask_ = EverythingMask; + uint8_t _mask_ = EverythingMask; void updateAttenuation(float3& multiplier) { attenuation2 = attenuation; @@ -194,71 +175,14 @@ struct RadiancePRD }; - -static __forceinline__ __device__ void traceRadiance( - OptixTraversableHandle handle, - float3 ray_origin, - float3 ray_direction, - float tmin, - float tmax, - RadiancePRD* prd - ) -{ - // TODO: deduce stride from num ray-types passed in params - - unsigned int u0, u1; - packPointer( prd, u0, u1 ); - optixTrace( - handle, - ray_origin, - ray_direction, - tmin, - tmax, - 0.0f, // rayTime - OptixVisibilityMask( 1 | 2 ), - OPTIX_RAY_FLAG_NONE, - RAY_TYPE_RADIANCE, // SBT offset - RAY_TYPE_COUNT, // SBT stride - RAY_TYPE_RADIANCE, // missSBTIndex - u0, u1 ); -} - - -static __forceinline__ __device__ bool traceOcclusion( - OptixTraversableHandle handle, - float3 ray_origin, - float3 ray_direction, - float tmin, - float tmax, - RadiancePRD* prd - ) -{ - unsigned int u0, u1; - packPointer( prd, u0, u1 ); - optixTrace( - handle, - ray_origin, - ray_direction, - tmin, - tmax, - 0.0f, // rayTime - OptixVisibilityMask( 1 | 2 ), - OPTIX_RAY_FLAG_ENFORCE_ANYHIT, - RAY_TYPE_OCCLUSION, // SBT offset - RAY_TYPE_COUNT, // SBT stride - RAY_TYPE_OCCLUSION, // missSBTIndex - u0, u1); - return false;//??? -} - -static __forceinline__ __device__ void traceRadianceMasked( +static __forceinline__ __device__ void traceRadiance( OptixTraversableHandle handle, float3 ray_origin, float3 ray_direction, float tmin, float tmax, - char mask, - RadiancePRD *prd) + RadiancePRD *prd, + OptixVisibilityMask mask=255u) { unsigned int u0, u1; packPointer( prd, u0, u1 ); @@ -267,7 +191,7 @@ static __forceinline__ __device__ void traceRadianceMasked( ray_origin, ray_direction, tmin, tmax, 0.0f, // rayTime - OptixVisibilityMask(mask), + (mask), OPTIX_RAY_FLAG_DISABLE_ANYHIT, RAY_TYPE_RADIANCE, // SBT offset RAY_TYPE_COUNT, // SBT stride @@ -276,14 +200,14 @@ static __forceinline__ __device__ void traceRadianceMasked( } -static __forceinline__ __device__ void traceOcclusionMasked( +static __forceinline__ __device__ void traceOcclusion( OptixTraversableHandle handle, float3 ray_origin, float3 ray_direction, float tmin, float tmax, - char mask, - RadiancePRD *prd) + RadiancePRD *prd, + OptixVisibilityMask mask=255u) { unsigned int u0, u1; packPointer( prd, u0, u1 ); @@ -292,8 +216,8 @@ static __forceinline__ __device__ void traceOcclusionMasked( ray_origin, ray_direction, tmin, tmax, 0.0f, // rayTime - OptixVisibilityMask(mask), - OPTIX_RAY_FLAG_ENFORCE_ANYHIT, //OPTIX_RAY_FLAG_NONE, + (mask), + OPTIX_RAY_FLAG_ENFORCE_ANYHIT, RAY_TYPE_OCCLUSION, // SBT offset RAY_TYPE_COUNT, // SBT stride RAY_TYPE_OCCLUSION, // missSBTIndex diff --git a/zenovis/xinxinoptix/XAS.h b/zenovis/xinxinoptix/XAS.h new file mode 100644 index 0000000000..cdf02272db --- /dev/null +++ b/zenovis/xinxinoptix/XAS.h @@ -0,0 +1,134 @@ +#pragma once + +#include +#include "optix.h" +#include "raiicuda.h" + +#include +#include +#include + +#define RETURN_IF_CUDA_ERROR( call ) \ + cudaError_t error = call; \ + if( error != cudaSuccess ) \ + { \ + printf("CUDA call ( \" %s \" ) failed with error: %s (%s: %d) \n", \ + #call, cudaGetErrorString( error ), __FILE__, __LINE__); \ + cudaGetLastError(); \ + return; \ + } \ + //(error); \ + \ + +namespace xinxinoptix { + + inline void buildXAS(const OptixDeviceContext& context, OptixAccelBuildOptions& accel_options, OptixBuildInput& build_input, + raii& _bufferXAS_, OptixTraversableHandle& _handleXAS_, bool verbose=false) { + + _bufferXAS_.reset(); + _handleXAS_ = 0llu; + + size_t temp_buffer_size {}; + size_t output_buffer_size {}; + { + OptixAccelBufferSizes xas_buffer_sizes; + OPTIX_CHECK( optixAccelComputeMemoryUsage(context, + &accel_options, + &build_input, + 1, // num build inputs + &xas_buffer_sizes + ) ); + + temp_buffer_size = roundUp(xas_buffer_sizes.tempSizeInBytes, 128u); + output_buffer_size = roundUp( xas_buffer_sizes.outputSizeInBytes, 128u ); + + if (verbose) { + float temp_mb = (float)temp_buffer_size / (1024 * 1024); + float output_mb = (float)output_buffer_size / (1024 * 1024); + printf("Requires %f MB temp buffer and %f MB output buffer \n", temp_mb, output_mb); + } + } + + raii bufferTemp{}; + RETURN_IF_CUDA_ERROR( cudaMalloc(reinterpret_cast( &bufferTemp.handle ), temp_buffer_size ) ); + + const bool COMPACTION = accel_options.buildFlags & OPTIX_BUILD_FLAG_ALLOW_COMPACTION; + + if (!COMPACTION) { + + RETURN_IF_CUDA_ERROR( cudaMalloc( reinterpret_cast( &_bufferXAS_.reset() ), output_buffer_size ) ); + + OPTIX_CHECK( optixAccelBuild( context, + nullptr, // CUDA stream + &accel_options, &build_input, + 1, // num build inputs + bufferTemp, + temp_buffer_size, + _bufferXAS_, + output_buffer_size, + &_handleXAS_, + nullptr, + 0 ) ); + } else { + + raii output_buffer_xas {}; + RETURN_IF_CUDA_ERROR( cudaMalloc( reinterpret_cast( &output_buffer_xas ), output_buffer_size + sizeof(size_t)) ); + + OptixAccelEmitDesc emitProperty {}; + emitProperty.type = OPTIX_PROPERTY_TYPE_COMPACTED_SIZE; + emitProperty.result = ( CUdeviceptr )( (char*)(CUdeviceptr)output_buffer_xas.handle + output_buffer_size ); + + OPTIX_CHECK( optixAccelBuild( context, + 0, // CUDA stream + &accel_options, &build_input, + 1, // num build inputs + bufferTemp, + temp_buffer_size, + output_buffer_xas, + output_buffer_size, + &_handleXAS_, + &emitProperty, // emitted property list + 1 // num emitted properties + ) ); + + bufferTemp.reset(); + size_t compacted_size{}; + CUDA_CHECK( cudaMemcpy( &compacted_size, (void*)emitProperty.result, sizeof( size_t ), cudaMemcpyDeviceToHost ) ); + + if( compacted_size < output_buffer_size ) + { + RETURN_IF_CUDA_ERROR( cudaMalloc( reinterpret_cast( &_bufferXAS_ ), compacted_size ) ); + OPTIX_CHECK( optixAccelCompact( context, 0, _handleXAS_, _bufferXAS_, compacted_size, &_handleXAS_ ) ); + } + else + { + _bufferXAS_ = std::move(output_buffer_xas); + } + } // COMPACTION + } + + inline void buildIAS(OptixDeviceContext& context, OptixAccelBuildOptions& accel_options, std::vector& instances, + raii& bufferIAS, OptixTraversableHandle& handleIAS) + { + raii d_instances; + const size_t size_in_bytes = sizeof( OptixInstance ) * instances.size(); + CUDA_CHECK( cudaMalloc( reinterpret_cast( &d_instances.reset() ), size_in_bytes ) ); + CUDA_CHECK( cudaMemcpy( + reinterpret_cast( (CUdeviceptr)d_instances ), + instances.data(), + size_in_bytes, + cudaMemcpyHostToDevice + ) ); + + OptixBuildInput instance_input{}; + instance_input.type = OPTIX_BUILD_INPUT_TYPE_INSTANCES; + instance_input.instanceArray.instances = d_instances; + instance_input.instanceArray.numInstances = static_cast( instances.size() ); + + // OptixAccelBuildOptions accel_options{}; + // accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION | OPTIX_BUILD_FLAG_ALLOW_RANDOM_VERTEX_ACCESS | OPTIX_BUILD_FLAG_ALLOW_RANDOM_INSTANCE_ACCESS; + // accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; + + buildXAS(context, accel_options, instance_input, bufferIAS, handleIAS); + } +} \ No newline at end of file diff --git a/zenovis/xinxinoptix/ies/ies.cpp b/zenovis/xinxinoptix/ies/ies.cpp new file mode 100644 index 0000000000..3f274da546 --- /dev/null +++ b/zenovis/xinxinoptix/ies/ies.cpp @@ -0,0 +1,405 @@ +/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation + * + * SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +#define _USE_MATH_DEFINES +#include +#include + +#include "Host.h" +#include "ies.h" + +#ifndef M_PI_F +#define M_PI_F M_PI +#endif + +namespace blender { + +bool IESFile::load(const string &ies) +{ + clear(); + if (!parse(ies) || !process()) { + clear(); + return false; + } + return true; +} + +void IESFile::clear() +{ + intensity.clear(); + v_angles.clear(); + h_angles.clear(); +} + +int IESFile::packed_size() +{ + if (v_angles.size() && h_angles.size() > 0) { + return 2 + h_angles.size() + v_angles.size() + h_angles.size() * v_angles.size(); + } + return 0; +} + +void IESFile::pack(float *data) +{ + if (v_angles.size() && h_angles.size()) { + *(data++) = __int_as_float(h_angles.size()); + *(data++) = __int_as_float(v_angles.size()); + + memcpy(data, &h_angles[0], h_angles.size() * sizeof(float)); + data += h_angles.size(); + memcpy(data, &v_angles[0], v_angles.size() * sizeof(float)); + data += v_angles.size(); + + for (int h = 0; h < intensity.size(); h++) { + memcpy(data, &intensity[h][0], v_angles.size() * sizeof(float)); + data += v_angles.size(); + } + } +} + +class IESTextParser { + public: + vector text; + char *data; + bool error; + + IESTextParser(const string &str) : text(str.begin(), str.end()), error(false) + { + std::replace(text.begin(), text.end(), ',', ' '); + data = strstr(&text[0], "\nTILT="); + } + + bool eof() + { + return (data == NULL) || (data[0] == '\0'); + } + + bool has_error() + { + return error; + } + + double get_double() + { + if (eof()) { + error = true; + return 0.0; + } + char *old_data = data; + double val = strtod(data, &data); + if (data == old_data) { + data = NULL; + error = true; + return 0.0; + } + return val; + } + + long get_long() + { + if (eof()) { + error = true; + return 0; + } + char *old_data = data; + long val = strtol(data, &data, 10); + if (data == old_data) { + data = NULL; + error = true; + return 0; + } + return val; + } +}; + +bool IESFile::parse(const string &ies) +{ + if (ies.empty()) { + return false; + } + + IESTextParser parser(ies); + if (parser.eof()) { + return false; + } + + /* Handle the tilt data block. */ + if (strncmp(parser.data, "\nTILT=INCLUDE", 13) == 0) { + parser.data += 13; + parser.get_double(); /* Lamp to Luminaire geometry */ + int num_tilt = parser.get_long(); /* Amount of tilt angles and factors */ + /* Skip over angles and factors. */ + for (int i = 0; i < 2 * num_tilt; i++) { + parser.get_double(); + } + } + else { + /* Skip to next line. */ + parser.data = strstr(parser.data + 1, "\n"); + } + + if (parser.eof()) { + return false; + } + parser.data++; + + parser.get_long(); /* Number of lamps */ + parser.get_double(); /* Lumens per lamp */ + double factor = parser.get_double(); /* Candela multiplier */ + int v_angles_num = parser.get_long(); /* Number of vertical angles */ + int h_angles_num = parser.get_long(); /* Number of horizontal angles */ + type = (IESType)parser.get_long(); /* Photometric type */ + + /* TODO(lukas): Test whether the current type B processing can also deal with type A files. + * In theory the only difference should be orientation which we ignore anyways, but with IES you + * never know... + */ + if (type != TYPE_B && type != TYPE_C) { + return false; + } + + parser.get_long(); /* Unit of the geometry data */ + parser.get_double(); /* Width */ + parser.get_double(); /* Length */ + parser.get_double(); /* Height */ + factor *= parser.get_double(); /* Ballast factor */ + factor *= parser.get_double(); /* Ballast-Lamp Photometric factor */ + parser.get_double(); /* Input Watts */ + + /* Intensity values in IES files are specified in candela (lumen/sr), a photometric quantity. + * Cycles expects radiometric quantities, though, which requires a conversion. + * However, the Luminous efficacy (ratio of lumens per Watt) depends on the spectral distribution + * of the light source since lumens take human perception into account. + * Since this spectral distribution is not known from the IES file, a typical one must be + * assumed. The D65 standard illuminant has a Luminous efficacy of 177.83, which is used here to + * convert to Watt/sr. A more advanced approach would be to add a Blackbody Temperature input to + * the node and numerically integrate the Luminous efficacy from the resulting spectral + * distribution. Also, the Watt/sr value must be multiplied by 4*pi to get the Watt value that + * Cycles expects for lamp strength. Therefore, the conversion here uses 4*pi/177.83 as a Candela + * to Watt factor. + */ + factor *= 0.0706650768394; + + v_angles.reserve(v_angles_num); + for (int i = 0; i < v_angles_num; i++) { + v_angles.push_back((float)parser.get_double()); + } + + h_angles.reserve(h_angles_num); + for (int i = 0; i < h_angles_num; i++) { + h_angles.push_back((float)parser.get_double()); + } + + intensity.resize(h_angles_num); + for (int i = 0; i < h_angles_num; i++) { + intensity[i].reserve(v_angles_num); + for (int j = 0; j < v_angles_num; j++) { + intensity[i].push_back((float)(factor * parser.get_double())); + } + } + + return !parser.has_error(); +} + +bool IESFile::process_type_b() +{ + vector> newintensity; + newintensity.resize(v_angles.size()); + for (int i = 0; i < v_angles.size(); i++) { + newintensity[i].reserve(h_angles.size()); + for (int j = 0; j < h_angles.size(); j++) { + newintensity[i].push_back(intensity[j][i]); + } + } + intensity.swap(newintensity); + h_angles.swap(v_angles); + + float h_first = h_angles[0], h_last = h_angles[h_angles.size() - 1]; + if (h_last != 90.0f) { + return false; + } + + if (h_first == 0.0f) { + /* The range in the file corresponds to 90°-180°, we need to mirror that to get the + * full 180° range. */ + vector new_h_angles; + vector> new_intensity; + int hnum = h_angles.size(); + new_h_angles.reserve(2 * hnum - 1); + new_intensity.reserve(2 * hnum - 1); + for (int i = hnum - 1; i > 0; i--) { + new_h_angles.push_back(90.0f - h_angles[i]); + new_intensity.push_back(intensity[i]); + } + for (int i = 0; i < hnum; i++) { + new_h_angles.push_back(90.0f + h_angles[i]); + new_intensity.push_back(intensity[i]); + } + h_angles.swap(new_h_angles); + intensity.swap(new_intensity); + } + else if (h_first == -90.0f) { + /* We have full 180° coverage, so just shift to match the angle range convention. */ + for (int i = 0; i < h_angles.size(); i++) { + h_angles[i] += 90.0f; + } + } + /* To get correct results with the cubic interpolation in the kernel, the horizontal range + * has to cover all 360°. Therefore, we copy the 0° entry to 360° to ensure full coverage + * and seamless interpolation. */ + h_angles.push_back(360.0f); + intensity.push_back(intensity[0]); + + float v_first = v_angles[0], v_last = v_angles[v_angles.size() - 1]; + if (v_last != 90.0f) { + return false; + } + + if (v_first == 0.0f) { + /* The range in the file corresponds to 90°-180°, we need to mirror that to get the + * full 180° range. */ + vector new_v_angles; + int hnum = h_angles.size(); + int vnum = v_angles.size(); + new_v_angles.reserve(2 * vnum - 1); + for (int i = vnum - 1; i > 0; i--) { + new_v_angles.push_back(90.0f - v_angles[i]); + } + for (int i = 0; i < vnum; i++) { + new_v_angles.push_back(90.0f + v_angles[i]); + } + for (int i = 0; i < hnum; i++) { + vector new_intensity; + new_intensity.reserve(2 * vnum - 1); + for (int j = vnum - 2; j >= 0; j--) { + new_intensity.push_back(intensity[i][j]); + } + new_intensity.insert(new_intensity.end(), intensity[i].begin(), intensity[i].end()); + intensity[i].swap(new_intensity); + } + v_angles.swap(new_v_angles); + } + else if (v_first == -90.0f) { + /* We have full 180° coverage, so just shift to match the angle range convention. */ + for (int i = 0; i < v_angles.size(); i++) { + v_angles[i] += 90.0f; + } + } + + return true; +} + +bool IESFile::process_type_c() +{ + if (h_angles[0] == 90.0f) { + /* Some files are stored from 90° to 270°, so we just rotate them to the regular 0°-180° range + * here. */ + for (int i = 0; i < h_angles.size(); i++) { + h_angles[i] -= 90.0f; + } + } + + if (h_angles[0] != 0.0f) { + return false; + } + + if (h_angles.size() == 1) { + h_angles.push_back(360.0f); + intensity.push_back(intensity[0]); + } + + if (h_angles[h_angles.size() - 1] == 90.0f) { + /* Only one quadrant is defined, so we need to mirror twice (from one to two, then to four). + * Since the two->four mirroring step might also be required if we get an input of two + * quadrants, we only do the first mirror here and later do the second mirror in either case. + */ + int hnum = h_angles.size(); + for (int i = hnum - 2; i >= 0; i--) { + h_angles.push_back(180.0f - h_angles[i]); + intensity.push_back(intensity[i]); + } + } + + if (h_angles[h_angles.size() - 1] == 180.0f) { + /* Mirror half to the full range. */ + int hnum = h_angles.size(); + for (int i = hnum - 2; i >= 0; i--) { + h_angles.push_back(360.0f - h_angles[i]); + intensity.push_back(intensity[i]); + } + } + + /* Some files skip the 360° entry (contrary to standard) because it's supposed to be identical to + * the 0° entry. If the file has a discernible order in its spacing, just fix this. */ + if (h_angles[h_angles.size() - 1] != 360.0f) { + int hnum = h_angles.size(); + float last_step = h_angles[hnum - 1] - h_angles[hnum - 2]; + float first_step = h_angles[1] - h_angles[0]; + float difference = 360.0f - h_angles[hnum - 1]; + if (last_step == difference || first_step == difference) { + h_angles.push_back(360.0f); + intensity.push_back(intensity[0]); + } + else { + return false; + } + } + + float v_first = v_angles[0], v_last = v_angles[v_angles.size() - 1]; + if (v_first == 90.0f) { + if (v_last != 180.0f) { + return false; + } + } + else if (v_first != 0.0f) { + return false; + } + + return true; +} + +bool IESFile::process() +{ + if (h_angles.size() == 0 || v_angles.size() == 0) { + return false; + } + + if (type == TYPE_B) { + if (!process_type_b()) { + return false; + } + } + else { + assert(type == TYPE_C); + if (!process_type_c()) { + return false; + } + } + + assert(v_angles[0] == 0.0f || v_angles[0] == 90.0f); + assert(h_angles[0] == 0.0f); + assert(h_angles[h_angles.size() - 1] == 360.0f); + + /* Convert from deg to rad. */ + for (int i = 0; i < v_angles.size(); i++) { + v_angles[i] *= M_PI_F / 180.f; + } + for (int i = 0; i < h_angles.size(); i++) { + h_angles[i] *= M_PI_F / 180.f; + } + + return true; +} + +IESFile::~IESFile() +{ + clear(); +} + +} // namespace end \ No newline at end of file diff --git a/zenovis/xinxinoptix/ies/ies.h b/zenovis/xinxinoptix/ies/ies.h new file mode 100644 index 0000000000..aba3b19cfc --- /dev/null +++ b/zenovis/xinxinoptix/ies/ies.h @@ -0,0 +1,53 @@ +/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation + * + * SPDX-License-Identifier: Apache-2.0 */ + +#ifndef __UTIL_IES_H__ +#define __UTIL_IES_H__ + +#include +#include + +namespace blender { +using namespace std; + +class IESFile { + public: + IESFile() {} + ~IESFile(); + + int packed_size(); + void pack(float *data); + + float coneAngle() { + if (v_angles.empty()) + return 0.0f; + + return max(v_angles.front(), v_angles.back()); + } + + bool load(const string &ies); + void clear(); + + protected: + bool parse(const string &ies); + bool process(); + bool process_type_b(); + bool process_type_c(); + + /* The brightness distribution is stored in spherical coordinates. + * The horizontal angles correspond to theta in the regular notation + * and always span the full range from 0° to 360°. + * The vertical angles correspond to phi and always start at 0°. */ + std::vector v_angles, h_angles; + /* The actual values are stored here, with every entry storing the values + * of one horizontal segment. */ + std::vector> intensity; + + /* Types of angle representation in IES files. Currently, only B and C are supported. */ + enum IESType { TYPE_A = 3, TYPE_B = 2, TYPE_C = 1 } type; +}; + +} // namespace end + +#endif /* __UTIL_IES_H__ */ diff --git a/zenovis/xinxinoptix/optixPathTracer.cpp b/zenovis/xinxinoptix/optixPathTracer.cpp index 09985c2bbb..d0b5b91410 100644 --- a/zenovis/xinxinoptix/optixPathTracer.cpp +++ b/zenovis/xinxinoptix/optixPathTracer.cpp @@ -1,7 +1,4 @@ -// // this part of code is modified from nvidia's optix example - - #include // Needs to be included before gl_interop #include @@ -14,6 +11,7 @@ #include +#include #include #include #include @@ -22,7 +20,6 @@ #include #include #include -#include #include #include #ifdef __linux__ @@ -31,7 +28,8 @@ #endif //#include - +#include "XAS.h" +#include "magic_enum.hpp" #include "optixPathTracer.h" #include @@ -42,6 +40,7 @@ #include "optixVolume.h" #include "zeno/core/Session.h" +#include #include #include #include @@ -57,9 +56,12 @@ #include "xinxinoptixapi.h" #include "OptiXStuff.h" #include +#include #include #include -#include +#include + +#include #include #include @@ -67,6 +69,12 @@ #include #include +#include "LightBounds.h" +#include "LightTree.h" + +#include "LightBounds.h" +#include "LightTree.h" + #include "ChiefDesignerEXR.h" using namespace zeno::ChiefDesignerEXR; @@ -167,19 +175,20 @@ std::optional> output_buffer_specular; std::optional> output_buffer_transmit; std::optional> output_buffer_background; using Vertex = float4; -std::vector g_lightMesh; -std::vector g_lightColor; + struct PathTracerState { OptixDeviceContext context = 0; - OptixTraversableHandle root_handle; - raii root_output_buffer; + OptixTraversableHandle rootHandleIAS; + raii rootBufferIAS; + + OptixTraversableHandle meshHandleIAS; + raii meshBufferIAS; - OptixTraversableHandle m_ias_handle; OptixTraversableHandle gas_handle = {}; // Traversable handle for triangle AS raii d_gas_output_buffer; // Triangle AS memory - raii m_d_ias_output_buffer; + raii d_vertices; raii d_clr; raii d_nrm; @@ -211,7 +220,6 @@ struct PathTracerState raii stream; raii accum_buffer_p; - raii albedo_buffer_p; raii normal_buffer_p; @@ -296,25 +304,26 @@ static std::vector g_lightMark = //TRIANGLE_COUNT { 0 }; -static std::vector g_lights={ - ParallelogramLight{ - /*corner=*/ - /*v1=*/ - /*v2=*/ - /*normal=*/ - /*emission=*/ - }, -}; -/* -static std::vector g_emission_colors= // MAT_COUNT -{ - {0,0,0}, -}; -static std::vector g_diffuse_colors= // MAT_COUNT -{ - {0.8f,0.8f,0.8f}, -}; -*/ + +struct LightsWrapper { + std::vector g_lightPlanes; + std::vector g_lightSpheres; + std::vector g_lights; + + OptixTraversableHandle lightPlanesGas{}; + raii lightPlanesGasBuffer{}; + + OptixTraversableHandle lightSpheresGas{}; + raii lightSpheresGasBuffer{}; + + raii lightBitTrailsPtr; + raii lightTreeNodesPtr; + raii lightTreeDummyPtr; + + void reset() { *this = {}; } + +} lightsWrapper; + std::map g_mtlidlut; // MAT_COUNT struct InstData @@ -381,7 +390,7 @@ static void initLaunchParams( PathTracerState& state ) state.params.handle = state.gas_handle; //#else } else { - state.params.handle = state.m_ias_handle; + state.params.handle = state.rootHandleIAS; } //#endif CUDA_CHECK( cudaMalloc( @@ -506,7 +515,7 @@ static void launchSubframe( sutil::CUDAOutputBuffer& output_buffer, Path state.params.frame_buffer_S = (*output_buffer_specular ).map(); state.params.frame_buffer_T = (*output_buffer_transmit ).map(); state.params.frame_buffer_B = (*output_buffer_background).map(); - state.params.num_lights = g_lights.size(); + state.params.num_lights = lightsWrapper.g_lights.size(); state.params.denoise = denoise; for(int j=0;j<1;j++){ for(int i=0;i<1;i++){ @@ -543,7 +552,14 @@ static void launchSubframe( sutil::CUDAOutputBuffer& output_buffer, Path (*output_buffer_specular ).unmap(); (*output_buffer_transmit ).unmap(); (*output_buffer_background).unmap(); - CUDA_SYNC_CHECK(); + + try { + CUDA_SYNC_CHECK(); + } + catch(std::exception const& e) + { + std::cout << "Exception: " << e.what() << "\n"; + } } @@ -566,163 +582,75 @@ static void displaySubframe( sutil::CUDAOutputBuffer& output_buffer, sut //output_buffer_o.getHostPointer(); } +void updateSphereXAS() { + timer.tick(); + //cleanupSpheresGPU(); -OptixTraversableHandle uniform_sphere_gas_handle {}; -raii uniform_sphere_d_gas_output_buffer {}; - -void updateUniformSphereGAS() { - - if (uniform_sphere_gas_handle == 0 && !xinxinoptix::LutSpheresTransformed.empty()) { - - makeUniformSphereGAS(state.context, uniform_sphere_gas_handle, uniform_sphere_d_gas_output_buffer); + buildInstancedSpheresGAS(state.context, sphereInstanceGroupAgentList); - printf("uniform_spheres_gas_handle %llu \n", uniform_sphere_gas_handle); + if (uniformed_sphere_gas_handle == 0 && !xinxinoptix::SphereTransformedTable.empty()) { + buildUniformedSphereGAS(state.context, uniformed_sphere_gas_handle, uniformed_sphere_gas_buffer); } -} - -struct SphereInstanceAgent { - SphereInstanceGroupBase base{}; - - std::vector radius_list{}; - std::vector center_list{}; - - raii inst_sphere_gas_buffer {}; - OptixTraversableHandle inst_sphere_gas_handle {}; - - SphereInstanceAgent(SphereInstanceGroupBase _base):base(_base){} - //SphereInstanceAgent(SphereInstanceBase &_base):base(_base){} - ~SphereInstanceAgent() { - inst_sphere_gas_handle = 0; - inst_sphere_gas_buffer.reset(); - } -}; -std::vector> sphereInstanceGroupAgentList; - -void updateInstancedSpheresGAS() { + std::vector optix_instances; + optix_instances.reserve(sphereInstanceGroupAgentList.size() + SphereTransformedTable.size()); + const float mat3r4c[12] = {1,0,0,0,0,1,0,0,0,0,1,0}; - OptixAccelBuildOptions accel_options {}; - accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; - accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION | OPTIX_BUILD_FLAG_ALLOW_RANDOM_VERTEX_ACCESS | OPTIX_BUILD_FLAG_ALLOW_RANDOM_INSTANCE_ACCESS; - - raii _vertex_buffer; - raii _radius_buffer; + size_t instance_idx = 0u; + size_t sbt_offset = 0u; for (auto& sphereAgent : sphereInstanceGroupAgentList) { - const auto sphere_count = sphereAgent->center_list.size(); - if (sphere_count == 0) continue; - - { - auto data_length = sizeof( zeno::vec3f ) * sphere_count; - - CUDA_CHECK( cudaMalloc( reinterpret_cast( &_vertex_buffer ), data_length) ); - CUDA_CHECK( cudaMemcpy( reinterpret_cast( (CUdeviceptr)_vertex_buffer ), sphereAgent->center_list.data(), - data_length, cudaMemcpyHostToDevice ) ); - } - - { - auto data_length = sizeof( float ) * sphere_count; - - CUDA_CHECK( cudaMalloc( reinterpret_cast( &_radius_buffer ), data_length) ); - CUDA_CHECK( cudaMemcpy( reinterpret_cast( (CUdeviceptr)_radius_buffer ), sphereAgent->radius_list.data(), - data_length, cudaMemcpyHostToDevice ) ); - } - - OptixBuildInput sphere_input{}; + if (sphereAgent->inst_sphere_gas_handle == 0) continue; - sphere_input.type = OPTIX_BUILD_INPUT_TYPE_SPHERES; - sphere_input.sphereArray.numVertices = sphere_count; - sphere_input.sphereArray.vertexBuffers = &_vertex_buffer; - sphere_input.sphereArray.radiusBuffers = &_radius_buffer; - //sphere_input.sphereArray.singleRadius = false; - //sphere_input.sphereArray.vertexStrideInBytes = 12; - //sphere_input.sphereArray.radiusStrideInBytes = 4; + OptixInstance inst{}; + ++instance_idx; - uint32_t sphere_input_flags[1] = {OPTIX_GEOMETRY_FLAG_REQUIRE_SINGLE_ANYHIT_CALL}; - - sphere_input.sphereArray.flags = sphere_input_flags; - sphere_input.sphereArray.numSbtRecords = 1; - sphere_input.sphereArray.sbtIndexOffsetBuffer = 0; - sphere_input.sphereArray.sbtIndexOffsetSizeInBytes = 0; - sphere_input.sphereArray.sbtIndexOffsetStrideInBytes = 0; + auto combinedID = sphereAgent->base.materialID + ":" + std::to_string(ShaderMaker::Sphere); + auto shader_index = OptixUtil::matIDtoShaderIndex[combinedID]; - updateSphereGAS(state.context, sphere_input, accel_options, sphereAgent->inst_sphere_gas_buffer, sphereAgent->inst_sphere_gas_handle); + sbt_offset = shader_index * RAY_TYPE_COUNT; - _vertex_buffer.reset(); - _radius_buffer.reset(); + inst.flags = OPTIX_INSTANCE_FLAG_NONE; + inst.sbtOffset = sbt_offset; + inst.instanceId = instance_idx; + inst.visibilityMask = DefaultMatMask; + inst.traversableHandle = sphereAgent->inst_sphere_gas_handle; - sphereAgent->center_list.clear(); - sphereAgent->radius_list.clear(); + memcpy(inst.transform, mat3r4c, sizeof(float) * 12); + optix_instances.push_back( inst ); } -} - -OptixTraversableHandle crowded_sphere_gas_handle {}; -raii crowded_sphere_d_gas_output_buffer {}; - -void updateCrowdedSpheresGAS() { - const auto& dSphereList = xinxinoptix::SpheresCrowded; + if (uniformed_sphere_gas_handle != 0) { - const size_t sphere_count = dSphereList.center_list.size(); - if (sphere_count == 0) {return;} - - OptixAccelBuildOptions accel_options {}; - accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; - accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_RANDOM_VERTEX_ACCESS; + for(auto& [key, dsphere] : SphereTransformedTable) { - raii d_vertex_buffer{}; - raii d_radius_buffer{}; - raii d_sbtidx_buffer{}; - - { - auto data_length = sizeof( zeno::vec3f ) * sphere_count; - - CUDA_CHECK( cudaMalloc( reinterpret_cast( &d_vertex_buffer.reset() ), data_length) ); - CUDA_CHECK( cudaMemcpy( reinterpret_cast( (CUdeviceptr)d_vertex_buffer ), dSphereList.center_list.data(), - data_length, cudaMemcpyHostToDevice ) ); - } - - { - auto data_length = sizeof( float ) * sphere_count; - - CUDA_CHECK( cudaMalloc( reinterpret_cast( &d_radius_buffer.reset() ), data_length) ); - CUDA_CHECK( cudaMemcpy( reinterpret_cast( (CUdeviceptr)d_radius_buffer ), dSphereList.radius_list.data(), - data_length, cudaMemcpyHostToDevice ) ); - } - - OptixBuildInput sphere_input{}; - - sphere_input.type = OPTIX_BUILD_INPUT_TYPE_SPHERES; - sphere_input.sphereArray.numVertices = sphere_count; - sphere_input.sphereArray.vertexBuffers = &d_vertex_buffer; - sphere_input.sphereArray.radiusBuffers = &d_radius_buffer; - //sphere_input.sphereArray.singleRadius = false; - //sphere_input.sphereArray.vertexStrideInBytes = 12; - //sphere_input.sphereArray.radiusStrideInBytes = 4; - sphere_input.sphereArray.primitiveIndexOffset = 0; + auto combinedID = dsphere.materialID + ":" + std::to_string(ShaderMaker::Sphere); + auto shader_index = OptixUtil::matIDtoShaderIndex[combinedID]; - { - auto data_length = sizeof( uint ) * sphere_count; + sbt_offset = shader_index * RAY_TYPE_COUNT; + + OptixInstance inst{}; + ++instance_idx; + + inst.flags = OPTIX_INSTANCE_FLAG_NONE; + inst.sbtOffset = sbt_offset; + inst.instanceId = instance_idx; + inst.visibilityMask = DefaultMatMask; + inst.traversableHandle = uniformed_sphere_gas_handle; - CUDA_CHECK( cudaMalloc( reinterpret_cast( &d_sbtidx_buffer.reset() ), data_length) ); - CUDA_CHECK( cudaMemcpy( reinterpret_cast( (CUdeviceptr)d_sbtidx_buffer ), dSphereList.sbtoffset_list.data(), - data_length, cudaMemcpyHostToDevice ) ); + auto transform_ptr = glm::value_ptr( dsphere.optix_transform ); + memcpy(inst.transform, transform_ptr, sizeof(float) * 12); + optix_instances.push_back( inst ); + } } - std::vector sphere_input_flags(dSphereList.sbt_count, OPTIX_GEOMETRY_FLAG_REQUIRE_SINGLE_ANYHIT_CALL); - - sphere_input.sphereArray.flags = sphere_input_flags.data(); - sphere_input.sphereArray.numSbtRecords = dSphereList.sbt_count; - sphere_input.sphereArray.sbtIndexOffsetBuffer = d_sbtidx_buffer; - sphere_input.sphereArray.sbtIndexOffsetSizeInBytes = sizeof(uint); - sphere_input.sphereArray.sbtIndexOffsetStrideInBytes = sizeof(uint); - - updateSphereGAS(state.context, sphere_input, accel_options, crowded_sphere_d_gas_output_buffer, crowded_sphere_gas_handle); + OptixAccelBuildOptions accel_options{}; + accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; + accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION | OPTIX_BUILD_FLAG_ALLOW_RANDOM_VERTEX_ACCESS | OPTIX_BUILD_FLAG_ALLOW_RANDOM_INSTANCE_ACCESS; - d_vertex_buffer.reset(); - d_radius_buffer.reset(); - d_sbtidx_buffer.reset(); + buildIAS(state.context, accel_options, optix_instances, sphereBufferXAS, sphereHandleXAS); + timer.tock("Build Sphere IAS"); } static void initCameraState() @@ -800,71 +728,8 @@ static void buildMeshAccelSplitMesh( PathTracerState& state, std::shared_ptr d_temp_buffer; - CUDA_CHECK(cudaMalloc((void**)&d_temp_buffer.reset(), gas_buffer_sizes.tempSizeInBytes)); - - assert(d_temp_buffer.handle % OPTIX_ACCEL_BUFFER_BYTE_ALIGNMENT == 0); - - // non-compacted output - raii d_buffer_temp_output_gas_and_compacted_size; - size_t compactedSizeOffset = roundUp( gas_buffer_sizes.outputSizeInBytes, 8ull ); - CUDA_CHECK(cudaMalloc((void**)&d_buffer_temp_output_gas_and_compacted_size.reset(), compactedSizeOffset + 8ull)); - - assert(d_buffer_temp_output_gas_and_compacted_size.handle % OPTIX_ACCEL_BUFFER_BYTE_ALIGNMENT == 0); - - OptixAccelEmitDesc emitProperty = {}; - emitProperty.type = OPTIX_PROPERTY_TYPE_COMPACTED_SIZE; - emitProperty.result = ( CUdeviceptr )( (char*)(CUdeviceptr)d_buffer_temp_output_gas_and_compacted_size + compactedSizeOffset ); - - OPTIX_CHECK( optixAccelBuild( - state.context, - 0, // CUDA stream - &accel_options, - &triangle_input, - 1, // num build inputs - d_temp_buffer, - gas_buffer_sizes.tempSizeInBytes, - d_buffer_temp_output_gas_and_compacted_size, - gas_buffer_sizes.outputSizeInBytes, - &mesh->gas_handle, - &emitProperty, // emitted property list - 1 // num emitted properties - ) ); - - d_temp_buffer.reset(); - //d_mat_indices.reset(); - - size_t compacted_gas_size; - CUDA_CHECK( cudaMemcpy( &compacted_gas_size, (void*)emitProperty.result, sizeof(size_t), cudaMemcpyDeviceToHost) ); - - if( compacted_gas_size < gas_buffer_sizes.outputSizeInBytes ) - { - CUDA_CHECK(cudaMalloc((void**)&mesh->d_gas_output_buffer.reset(), compacted_gas_size)); - - assert(mesh->d_gas_output_buffer.handle % OPTIX_ACCEL_BUFFER_BYTE_ALIGNMENT == 0); - - // use handle as input and output - OPTIX_CHECK( optixAccelCompact( state.context, 0, - mesh->gas_handle, mesh->d_gas_output_buffer, compacted_gas_size, &mesh->gas_handle ) ); - - d_buffer_temp_output_gas_and_compacted_size.reset(); - } - else - { - mesh->d_gas_output_buffer = std::move(d_buffer_temp_output_gas_and_compacted_size); - } - state.gas_handle = mesh->gas_handle; - + buildXAS(state.context, accel_options, triangle_input, mesh->d_gas_output_buffer, mesh->gas_handle); + mesh->dverts.reset(); mesh->dmats.reset(); mesh->didx.reset(); @@ -875,8 +740,7 @@ static size_t g_staticVertNum = 0; static size_t g_staticAndDynamicMeshNum = 0; static size_t g_staticAndDynamicVertNum = 0; -static void buildInstanceAccel(PathTracerState& state, int rayTypeCount, std::vector> m_meshes) -{ +static void buildMeshIAS(PathTracerState& state, int rayTypeCount, std::vector> m_meshes) { std::cout<<"IAS begin"< 0) { - - OptixInstance inst{}; - optix_instance_idx; - - sbt_offset = g_mtlidlut.size() * RAY_TYPE_COUNT; - inst.flags = OPTIX_INSTANCE_FLAG_NONE; - inst.sbtOffset = sbt_offset; - inst.instanceId = optix_instance_idx; - inst.visibilityMask = DefaultMatMask; - inst.traversableHandle = crowded_sphere_gas_handle; - - memcpy(inst.transform, mat3r4c, sizeof(float) * 12); - optix_instances.push_back( inst ); - } + OptixAccelBuildOptions accel_options{}; + accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; + accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION | OPTIX_BUILD_FLAG_ALLOW_RANDOM_VERTEX_ACCESS | OPTIX_BUILD_FLAG_ALLOW_RANDOM_INSTANCE_ACCESS; - for (auto& sphereAgent : sphereInstanceGroupAgentList) { + buildIAS(state.context, accel_options, optix_instances, state.meshBufferIAS, state.meshHandleIAS); + timer.tock("Build Mesh IAS"); +} - if (sphereAgent->inst_sphere_gas_handle == 0) continue; +void buildRootIAS() +{ + timer.tick(); + const float mat3r4c[12] = {1,0,0,0,0,1,0,0,0,0,1,0}; + std::vector optix_instances{}; + uint sbt_offset = 0u; + { + if (state.meshHandleIAS != 0u) { OptixInstance inst{}; - ++optix_instance_idx; - - auto combinedID = sphereAgent->base.materialID + ":" + std::to_string(ShaderMaker::Sphere); - auto shader_index = OptixUtil::matIDtoShaderIndex[combinedID]; - - sbt_offset = shader_index * RAY_TYPE_COUNT; inst.flags = OPTIX_INSTANCE_FLAG_NONE; - inst.sbtOffset = sbt_offset; - inst.instanceId = optix_instance_idx; + inst.sbtOffset = 0; + inst.instanceId = 0; inst.visibilityMask = DefaultMatMask; - inst.traversableHandle = sphereAgent->inst_sphere_gas_handle; + inst.traversableHandle = state.meshHandleIAS; memcpy(inst.transform, mat3r4c, sizeof(float) * 12); optix_instances.push_back( inst ); } + } - if (uniform_sphere_gas_handle != 0) { - - for(auto& [key, dsphere] : LutSpheresTransformed) { - - auto combinedID = dsphere.materialID + ":" + std::to_string(ShaderMaker::Sphere); - auto shader_index = OptixUtil::matIDtoShaderIndex[combinedID]; + auto optix_instance_idx = optix_instances.size()-1; - sbt_offset = shader_index * RAY_TYPE_COUNT; - - OptixInstance inst{}; - ++optix_instance_idx; - - inst.flags = OPTIX_INSTANCE_FLAG_NONE; - inst.sbtOffset = sbt_offset; - inst.instanceId = optix_instance_idx; - inst.visibilityMask = DefaultMatMask; - inst.traversableHandle = uniform_sphere_gas_handle; - - auto transform_ptr = glm::value_ptr( dsphere.optix_transform ); - memcpy(inst.transform, transform_ptr, sizeof(float) * 12); - optix_instances.push_back( inst ); - } + if (sphereHandleXAS != 0u) { + OptixInstance opinstance {}; + ++optix_instance_idx; + sbt_offset = 0u; + + opinstance.flags = OPTIX_INSTANCE_FLAG_NONE; + opinstance.instanceId = optix_instance_idx; + opinstance.sbtOffset = sbt_offset; + opinstance.visibilityMask = DefaultMatMask; + opinstance.traversableHandle = sphereHandleXAS; + memcpy(opinstance.transform, mat3r4c, sizeof(float) * 12); + optix_instances.push_back( opinstance ); } // process volume - { - for ( uint i=0; i( _optix_instances.size() ); - optix_instance.sbtOffset = sbt_offset; - optix_instance.visibilityMask = VolumeMatMask; //VOLUME_OBJECT; - optix_instance.traversableHandle = list_volume_accel[i]->handle; - getOptixTransform( *(list_volume[i]), optix_instance.transform ); // transform as stored in Grid + optix_instance.flags = OPTIX_INSTANCE_FLAG_NONE; + optix_instance.instanceId = optix_instance_idx; + optix_instance.sbtOffset = sbt_offset; + optix_instance.visibilityMask = VolumeMatMask; //VOLUME_OBJECT; + optix_instance.traversableHandle = list_volume_accel[i]->handle; + getOptixTransform( *(list_volume[i]), optix_instance.transform ); // transform as stored in Grid - optix_instances.push_back( optix_instance ); - } + optix_instances.push_back( optix_instance ); } - const size_t instances_size_in_bytes = sizeof( OptixInstance ) * optix_instances.size(); - raii d_instances; - CUDA_CHECK( cudaMalloc( reinterpret_cast( &d_instances.reset() ), instances_size_in_bytes ) ); - CUDA_CHECK( cudaMemcpy( - reinterpret_cast( (CUdeviceptr)d_instances ), - optix_instances.data(), - instances_size_in_bytes, - cudaMemcpyHostToDevice - ) ); + //process light + if (lightsWrapper.lightPlanesGas != 0) + { + ++optix_instance_idx; + OptixInstance opinstance {}; - OptixBuildInput instance_input{}; - instance_input.type = OPTIX_BUILD_INPUT_TYPE_INSTANCES; - instance_input.instanceArray.instances = d_instances; - instance_input.instanceArray.numInstances = static_cast( optix_instances.size() ); + opinstance.flags = OPTIX_INSTANCE_FLAG_NONE; + opinstance.instanceId = OPTIX_DEVICE_PROPERTY_LIMIT_MAX_INSTANCE_ID-1; + opinstance.sbtOffset = 0; + opinstance.visibilityMask = LightMatMask; + opinstance.traversableHandle = lightsWrapper.lightPlanesGas; + memcpy(opinstance.transform, mat3r4c, sizeof(float) * 12); - OptixAccelBuildOptions accel_options{}; - accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION | OPTIX_BUILD_FLAG_ALLOW_RANDOM_VERTEX_ACCESS | OPTIX_BUILD_FLAG_ALLOW_RANDOM_INSTANCE_ACCESS; - accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; - - OptixAccelBufferSizes ias_buffer_sizes; - OPTIX_CHECK( optixAccelComputeMemoryUsage( - state.context, - &accel_options, - &instance_input, - 1, // num build inputs - &ias_buffer_sizes - ) ); + optix_instances.push_back( opinstance ); + } - raii d_temp_buffer; - CUDA_CHECK( cudaMalloc( - reinterpret_cast( &d_temp_buffer.reset() ), - roundUp(ias_buffer_sizes.tempSizeInBytes, 128ull) - ) ); + if (lightsWrapper.lightSpheresGas != 0) + { + ++optix_instance_idx; + OptixInstance opinstance {}; - assert(d_temp_buffer.handle % OPTIX_ACCEL_BUFFER_BYTE_ALIGNMENT == 0u); + auto combinedID = std::string("Default") + ":" + std::to_string(ShaderMaker::Sphere); + auto shader_index = OptixUtil::matIDtoShaderIndex[combinedID]; - CUDA_CHECK( cudaMalloc( - reinterpret_cast( &state.m_d_ias_output_buffer.reset() ), - roundUp(ias_buffer_sizes.outputSizeInBytes, 128ull) - ) ); + opinstance.flags = OPTIX_INSTANCE_FLAG_NONE; + opinstance.instanceId = OPTIX_DEVICE_PROPERTY_LIMIT_MAX_INSTANCE_ID; + opinstance.sbtOffset = shader_index * RAY_TYPE_COUNT;; + opinstance.visibilityMask = LightMatMask; + opinstance.traversableHandle = lightsWrapper.lightSpheresGas; + memcpy(opinstance.transform, mat3r4c, sizeof(float) * 12); - assert(state.m_d_ias_output_buffer.handle % OPTIX_ACCEL_BUFFER_BYTE_ALIGNMENT == 0u); + optix_instances.push_back( opinstance ); + } + + OptixAccelBuildOptions accel_options{}; + accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; + accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION | OPTIX_BUILD_FLAG_ALLOW_RANDOM_VERTEX_ACCESS | OPTIX_BUILD_FLAG_ALLOW_RANDOM_INSTANCE_ACCESS; - OPTIX_CHECK( optixAccelBuild( - state.context, - nullptr, // CUDA stream - &accel_options, - &instance_input, - 1, // num build inputs - d_temp_buffer, - ias_buffer_sizes.tempSizeInBytes, - state.m_d_ias_output_buffer, - ias_buffer_sizes.outputSizeInBytes, - &state.m_ias_handle, - nullptr, // emitted property list - 0 // num emitted properties - ) ); + buildIAS(state.context, accel_options, optix_instances, state.rootBufferIAS, state.rootHandleIAS); - timer.tock("done IAS build"); - std::cout<<"IAS end\n"; - //zeno::log_info("build IAS end"); + timer.tock("Build Root IAS"); + state.params.handle = state.rootHandleIAS; } + static void buildMeshAccel( PathTracerState& state ) { // @@ -1251,62 +1073,7 @@ static void buildMeshAccel( PathTracerState& state ) accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION | OPTIX_BUILD_FLAG_ALLOW_RANDOM_VERTEX_ACCESS | OPTIX_BUILD_FLAG_ALLOW_RANDOM_INSTANCE_ACCESS; accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; - OptixAccelBufferSizes gas_buffer_sizes; - //char log[2048]; size_t sizeof_log = sizeof( log ); - OPTIX_CHECK( optixAccelComputeMemoryUsage( - state.context, - &accel_options, - &triangle_input, - 1, // num_build_inputs - &gas_buffer_sizes - ) ); - - raii d_temp_buffer; - CUDA_CHECK(cudaMalloc((void**)&d_temp_buffer.reset(), gas_buffer_sizes.tempSizeInBytes)); - - // non-compacted output - raii d_buffer_temp_output_gas_and_compacted_size; - size_t compactedSizeOffset = roundUp( gas_buffer_sizes.outputSizeInBytes, 8ull ); - CUDA_CHECK(cudaMalloc((void**)&d_buffer_temp_output_gas_and_compacted_size.reset(), compactedSizeOffset + 8)); - - OptixAccelEmitDesc emitProperty = {}; - emitProperty.type = OPTIX_PROPERTY_TYPE_COMPACTED_SIZE; - emitProperty.result = ( CUdeviceptr )( (char*)(CUdeviceptr)d_buffer_temp_output_gas_and_compacted_size + compactedSizeOffset ); - - OPTIX_CHECK( optixAccelBuild( - state.context, - 0, // CUDA stream - &accel_options, - &triangle_input, - 1, // num build inputs - d_temp_buffer, - gas_buffer_sizes.tempSizeInBytes, - d_buffer_temp_output_gas_and_compacted_size, - gas_buffer_sizes.outputSizeInBytes, - &state.gas_handle, - &emitProperty, // emitted property list - 1 // num emitted properties - ) ); - - d_temp_buffer.reset(); - - size_t compacted_gas_size; - CUDA_CHECK( cudaMemcpy( &compacted_gas_size, (void*)emitProperty.result, sizeof(size_t), cudaMemcpyDeviceToHost) ); - - if( compacted_gas_size < gas_buffer_sizes.outputSizeInBytes ) - { - CUDA_CHECK(cudaMalloc((void**)&state.d_gas_output_buffer.reset(), compacted_gas_size)); - - // use handle as input and output - OPTIX_CHECK( optixAccelCompact( state.context, 0, - state.gas_handle, state.d_gas_output_buffer, compacted_gas_size, &state.gas_handle ) ); - - d_buffer_temp_output_gas_and_compacted_size.reset(); - } - else - { - state.d_gas_output_buffer = std::move(d_buffer_temp_output_gas_and_compacted_size); - } + buildXAS(state.context, accel_options, triangle_input, state.d_gas_output_buffer, state.d_gas_output_buffer); state.d_vertices.reset(); state.d_mat_indices.reset(); @@ -1446,9 +1213,6 @@ static void createSBT( PathTracerState& state ) cudaMemcpyHostToDevice ) ); - assert(d_hitgroup_records.handle % OPTIX_SBT_RECORD_ALIGNMENT == 0); - assert(hitgroup_record_size % OPTIX_SBT_RECORD_ALIGNMENT == 0); - state.sbt.raygenRecord = d_raygen_record; state.sbt.missRecordBase = d_miss_records; state.sbt.missRecordStrideInBytes = static_cast( miss_record_size ); @@ -1461,27 +1225,15 @@ static void createSBT( PathTracerState& state ) static void cleanupState( PathTracerState& state ) { - - OPTIX_CHECK( optixProgramGroupDestroy( state.raygen_prog_group ) ); + OPTIX_CHECK(optixProgramGroupDestroy(state.raygen_prog_group )); OPTIX_CHECK(optixProgramGroupDestroy(state.radiance_miss_group)); OPTIX_CHECK(optixProgramGroupDestroy(state.occlusion_miss_group)); - OPTIX_CHECK(optixModuleDestroy(OptixUtil::ray_module)); - //OPTIX_CHECK( optixProgramGroupDestroy( state.radiance_hit_group ) ); - //OPTIX_CHECK( optixProgramGroupDestroy( state.occlusion_hit_group ) ); - //OPTIX_CHECK( optixProgramGroupDestroy( state.radiance_hit_group2 ) ); - //OPTIX_CHECK( optixProgramGroupDestroy( state.occlusion_hit_group2 ) ); - //OPTIX_CHECK( optixProgramGroupDestroy( state.occlusion_miss_group ) ); - //OPTIX_CHECK( optixModuleDestroy( state.ptx_module ) ); - - OPTIX_CHECK( optixModuleDestroy( OptixUtil::sphere_module)); - - - + OPTIX_CHECK(optixModuleDestroy(OptixUtil::ray_module)); + OPTIX_CHECK(optixModuleDestroy(OptixUtil::sphere_module)); - //CUDA_CHECK( cudaFree( reinterpret_cast( state.sbt.raygenRecord ) ) ); - //CUDA_CHECK( cudaFree( reinterpret_cast( state.sbt.missRecordBase ) ) ); - //CUDA_CHECK( cudaFree( reinterpret_cast( state.sbt.hitgroupRecordBase ) ) ); + cleanupSpheresGPU(); + lightsWrapper.reset(); for (auto& ele : list_volume_accel) { cleanupVolumeAccel(*ele); @@ -1497,18 +1249,9 @@ static void cleanupState( PathTracerState& state ) cleanupVolume(*val); } OptixUtil::g_vdb_cached_map.clear(); + OptixUtil::g_ies.clear(); -// state.d_raygen_record.reset(); -// state.d_miss_records.reset(); -// state.d_hitgroup_records.reset(); -// state.d_vertices.reset(); -// state.d_gas_output_buffer.reset(); -// state.accum_buffer_p.reset(); -// state.albedo_buffer_p.reset(); -// state.normal_buffer_p.reset(); -// state.d_params.reset(); - - //state = {}; + std::cout << "optix cleanup" << std::endl; } static void detectHuangrenxunHappiness() { @@ -1685,7 +1428,7 @@ void optixinit( int argc, char* argv[] ) void updateVolume(uint volume_shader_offset) { - if (OptixUtil::g_vdb_cached_map.size() == 0) { return; } + if (OptixUtil::g_vdb_cached_map.empty()) { return; } OptixUtil::logInfoVRAM("Before update Volume"); @@ -1924,7 +1667,7 @@ void CopyInstMeshToGlobalMesh() } } -void UpdateGasAndIas(bool staticNeedUpdate) +void UpdateMeshGasAndIas(bool staticNeedUpdate) { //#ifdef USING_20XX // no archieve inst func in using20xx @@ -2070,7 +1813,7 @@ void UpdateGasAndIas(bool staticNeedUpdate) light_mark_size_in_bytes, cudaMemcpyHostToDevice)); timer.tock("done dynamic mesh update"); std::cout << "end copy\n"; - buildInstanceAccel(state, 2, g_meshPieces); + buildMeshIAS(state, 2, g_meshPieces); } //#endif } @@ -2081,6 +1824,10 @@ struct LightDat{ std::vector v2; std::vector normal; std::vector emission; + bool visible, doubleside; + uint8_t shape, type; + + std::string profileKey; }; static std::map lightdats; @@ -2088,13 +1835,16 @@ void unload_light(){ lightdats.clear(); } -void load_light(std::string const &key, float const*v0,float const*v1,float const*v2, float const*nor,float const*emi){ +void load_light(std::string const &key, float const*v0,float const*v1,float const*v2, float const*nor,float const*emi, bool visible, bool doubleside, int shape, int type, std::string& profileKey){ LightDat ld; ld.v0.assign(v0, v0 + 3); ld.v1.assign(v1, v1 + 3); ld.v2.assign(v2, v2 + 3); ld.normal.assign(nor, nor + 3); ld.emission.assign(emi, emi + 3); + ld.visible = visible; ld.doubleside = doubleside; + ld.shape = shape; ld.type = type; + ld.profileKey = profileKey; //zeno::log_info("light clr after read: {} {} {}", ld.emission[0],ld.emission[1],ld.emission[2]); lightdats[key] = ld; } @@ -2149,20 +1899,24 @@ static void addLightMesh(float3 corner, float3 v2, float3 v1, float3 normal, flo { float3 lc = corner; float3 vert0 = lc, vert1 = lc + v1, vert2 = lc + v2, vert3 = lc + v1 + v2; + + auto& g_lightMesh = lightsWrapper.g_lightPlanes; + g_lightMesh.push_back(make_float4(vert0.x, vert0.y, vert0.z, 0.f)); g_lightMesh.push_back(make_float4(vert1.x, vert1.y, vert1.z, 0.f)); g_lightMesh.push_back(make_float4(vert2.x, vert2.y, vert2.z, 0.f)); - g_lightColor.push_back(make_float4(emission.x, emission.y, emission.z, 0.0f)); - g_lightColor.push_back(make_float4(emission.x, emission.y, emission.z, 0.0f)); - g_lightColor.push_back(make_float4(emission.x, emission.y, emission.z, 0.0f)); g_lightMesh.push_back(make_float4(vert3.x, vert3.y, vert3.z, 0.f)); g_lightMesh.push_back(make_float4(vert2.x, vert2.y, vert2.z, 0.f)); g_lightMesh.push_back(make_float4(vert1.x, vert1.y, vert1.z, 0.f)); - g_lightColor.push_back(make_float4(emission.x, emission.y, emission.z, 0.0f)); - g_lightColor.push_back(make_float4(emission.x, emission.y, emission.z, 0.0f)); - g_lightColor.push_back(make_float4(emission.x, emission.y, emission.z, 0.0f)); } + +static void addLightSphere(float3 center, float radius) +{ + Vertex vt {center.x, center.y, center.z, radius}; + lightsWrapper.g_lightSpheres.push_back(vt); +} + static int uniformBufferInitialized = false; // void optixUpdateUniforms(std::vector & inConstants) void optixUpdateUniforms(void *inConstants, std::size_t size) { @@ -2176,57 +1930,234 @@ void optixUpdateUniforms(void *inConstants, std::size_t size) { uniformBufferInitialized = true; } -void optixupdatelight() { + +static void buildLightPlanesGAS( PathTracerState& state, std::vector& lightMesh, raii& bufferGas, OptixTraversableHandle& handleGas) +{ + if (lightMesh.empty()) { + handleGas = 0; + bufferGas.reset(); + return; + } + + const size_t vertices_size_in_bytes = lightMesh.size() * sizeof( Vertex ); + + raii d_lightMesh; + + CUDA_CHECK( cudaMalloc( reinterpret_cast( &d_lightMesh ), vertices_size_in_bytes ) ); + CUDA_CHECK( cudaMemcpy( + reinterpret_cast( (CUdeviceptr&)d_lightMesh ), + lightMesh.data(), vertices_size_in_bytes, + cudaMemcpyHostToDevice + ) ); + + std::vector triangle_input_flags(1, OPTIX_GEOMETRY_FLAG_REQUIRE_SINGLE_ANYHIT_CALL); + + OptixBuildInput triangle_input = {}; + triangle_input.type = OPTIX_BUILD_INPUT_TYPE_TRIANGLES; + triangle_input.triangleArray.vertexFormat = OPTIX_VERTEX_FORMAT_FLOAT3; + triangle_input.triangleArray.vertexStrideInBytes = sizeof( Vertex ); + triangle_input.triangleArray.numVertices = static_cast( lightMesh.size() ); + triangle_input.triangleArray.vertexBuffers = lightMesh.empty() ? nullptr : &d_lightMesh; + triangle_input.triangleArray.flags = triangle_input_flags.data(); + triangle_input.triangleArray.numSbtRecords = 1; // g_lightMesh.empty() ? 1 : g_mtlidlut.size(); + triangle_input.triangleArray.sbtIndexOffsetBuffer = 0;//state.d_mat_indices; + // triangle_input.triangleArray.sbtIndexOffsetSizeInBytes = sizeof( uint32_t ); + // triangle_input.triangleArray.sbtIndexOffsetStrideInBytes = sizeof( uint32_t ); + + OptixAccelBuildOptions accel_options {}; + accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; + accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION | OPTIX_BUILD_FLAG_ALLOW_RANDOM_VERTEX_ACCESS | OPTIX_BUILD_FLAG_ALLOW_RANDOM_INSTANCE_ACCESS; + + buildXAS(state.context, accel_options, triangle_input, bufferGas, handleGas); +} + +static void buildLightSpheresGAS( PathTracerState& state, std::vector& lightSpheres, raii& bufferGas, OptixTraversableHandle& handleGas) { + + if (lightSpheres.empty()) { + handleGas = 0; + bufferGas.reset(); + return; + } + + const size_t sphere_count = lightSpheres.size(); + + OptixAccelBuildOptions accel_options {}; + accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; + accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION | OPTIX_BUILD_FLAG_ALLOW_RANDOM_VERTEX_ACCESS | OPTIX_BUILD_FLAG_ALLOW_RANDOM_INSTANCE_ACCESS; + + raii d_vertex_buffer{}; + + { + auto data_length = sizeof( Vertex ) * sphere_count; + + CUDA_CHECK( cudaMalloc( reinterpret_cast( &d_vertex_buffer.reset() ), data_length) ); + CUDA_CHECK( cudaMemcpy( reinterpret_cast( (CUdeviceptr)d_vertex_buffer ), lightSpheres.data(), + data_length, cudaMemcpyHostToDevice ) ); + } + CUdeviceptr d_radius_buffer = (CUdeviceptr) ( (char*)d_vertex_buffer.handle + 12u ); + + OptixBuildInput sphere_input{}; + + sphere_input.type = OPTIX_BUILD_INPUT_TYPE_SPHERES; + sphere_input.sphereArray.numVertices = sphere_count; + sphere_input.sphereArray.vertexBuffers = &d_vertex_buffer; + sphere_input.sphereArray.radiusBuffers = &d_radius_buffer; + sphere_input.sphereArray.singleRadius = false; + sphere_input.sphereArray.vertexStrideInBytes = 16; + sphere_input.sphereArray.radiusStrideInBytes = 16; + //sphere_input.sphereArray.primitiveIndexOffset = 0; + + std::vector sphere_input_flags(1, OPTIX_GEOMETRY_FLAG_REQUIRE_SINGLE_ANYHIT_CALL); + + sphere_input.sphereArray.flags = sphere_input_flags.data(); + sphere_input.sphereArray.numSbtRecords = 1; + sphere_input.sphereArray.sbtIndexOffsetBuffer = 0; + // sphere_input.sphereArray.sbtIndexOffsetSizeInBytes = sizeof(uint); + // sphere_input.sphereArray.sbtIndexOffsetStrideInBytes = sizeof(uint); + + buildXAS(state.context, accel_options, sphere_input, bufferGas, handleGas); +} + +void buildLightTree() { camera_changed = true; + state.lightsbuf_p.reset(); + + state.params.lightTreeSampler = 0llu; + state.params.firstRectLightIdx = UINT_MAX; + state.params.firstSphereLightIdx = UINT_MAX; + + state.params.lights = 0llu; + state.params.num_lights = 0u; + + lightsWrapper.reset(); + + std::vector sortedLights; + sortedLights.reserve(lightdats.size()); + + for(const auto& [_, dat] : lightdats) { + sortedLights.push_back(dat); + } + + std::sort(sortedLights.begin(), sortedLights.end(), + [](const auto& a, const auto& b) { + return a.shape < b.shape; + }); + + uint32_t idx = 0u; + + uint32_t firstRectLightIdx = UINT_MAX; + uint32_t firstSphereLightIdx = UINT_MAX; + + for(uint32_t idx=0u; idx(dat.type).value_or(zeno::LightType::Diffuse); + light.shape = magic_enum::enum_cast(dat.shape).value_or(zeno::LightShape::Plane); + + if (light.shape == zeno::LightShape::Plane) { - //zeno::log_info("lights size {}", lightdats.size()); - - g_lights.clear(); - g_lightMesh.clear(); - g_lightColor.clear(); - - for (auto const &[key, dat]: lightdats) { - auto &light = g_lights.emplace_back(); - light.emission = make_float3( (float)(dat.emission[0]), (float)dat.emission[1], (float)dat.emission[2] ); - //zeno::log_info("light clr after read: {} {} {}", light.emission.x,light.emission.y,light.emission.z); - light.corner = make_float3( dat.v0[0], dat.v0[1], dat.v0[2] ); - //zeno::log_info("light clr after read: {} {} {}", light.corner.x,light.corner.y,light.corner.z); - light.v1 = make_float3( dat.v1[0], dat.v1[1], dat.v1[2] ); - //zeno::log_info("light clr after read: {} {} {}", light.v1.x,light.v1.y,light.v1.z); - light.v2 = make_float3( dat.v2[0], dat.v2[1], dat.v2[2] ); - //zeno::log_info("light clr after read: {} {} {}", light.v2.x,light.v2.y,light.v2.z); - light.normal = make_float3( dat.normal[0], dat.normal[1], dat.normal[2] ); - //zeno::log_info("light clr after read: {} {} {}", light.normal.x,light.normal.y,light.normal.z); - addLightMesh(light.corner, light.v2, light.v1, light.normal, light.emission); - } - - if(g_lights.size()) { - g_lights[0].cdf = length(cross(g_lights[0].v1, g_lights[0].v2)); - float a = g_lights[0].cdf; - for (int l = 1; l < g_lights.size(); l++) { - g_lights[l].cdf = g_lights[l - 1].cdf + length(cross(g_lights[l].v1, g_lights[l].v2)); + firstRectLightIdx = min(idx, firstRectLightIdx); + + light.setRectData(v0, v1, v2, light.N); + addLightMesh(v0, v2, v1, light.N, light.emission); + + } else if (light.shape == zeno::LightShape::Sphere) { + + firstSphereLightIdx = min(idx, firstSphereLightIdx); + + auto radius = fminf(length(v1), length(v2)) * 0.5f; + light.setSphereData(center, radius); + addLightSphere(center, radius); + + } else if (light.shape == zeno::LightShape::Point) { + light.point = {center}; + } + + if ( OptixUtil::g_ies.count(dat.profileKey) > 0 ) { + + auto& val = OptixUtil::g_ies.at(dat.profileKey); + light.ies = val.ptr.handle; + light.type = zeno::LightType::IES; + //light.shape = zeno::LightShape::Point; + auto radius = length(v1 + v2) * 0.5f; + light.setConeData(center, light.N, radius, val.coneAngle); + + } else if ( OptixUtil::g_tex.count(dat.profileKey) > 0 ) { + + auto& val = OptixUtil::g_tex.at(dat.profileKey); + light.tex = val->texture; } } -// for(int l=0;l( &state.lightsbuf_p.reset() ), - sizeof( ParallelogramLight ) * std::max(g_lights.size(),(size_t)1) - ) ); - state.params.lights = (ParallelogramLight*)(CUdeviceptr)state.lightsbuf_p; - if (g_lights.size()) - CUDA_CHECK( cudaMemcpy( + reinterpret_cast( &state.lightsbuf_p.reset() ), + sizeof( GenericLight ) * std::max(lightsWrapper.g_lights.size(),(size_t)1) + ) ); + + state.params.lights = (GenericLight*)(CUdeviceptr)state.lightsbuf_p; + CUDA_CHECK( cudaMemcpy( reinterpret_cast( (CUdeviceptr)state.lightsbuf_p ), - g_lights.data(), sizeof( ParallelogramLight ) * g_lights.size(), + lightsWrapper.g_lights.data(), sizeof( GenericLight ) * lightsWrapper.g_lights.size(), cudaMemcpyHostToDevice ) ); + + auto lsampler = pbrt::LightTreeSampler(lightsWrapper.g_lights); + + raii& lightBitTrailsPtr = lightsWrapper.lightBitTrailsPtr; + raii& lightTreeNodesPtr = lightsWrapper.lightTreeNodesPtr; + raii& lightTreeDummyPtr = lightsWrapper.lightTreeDummyPtr; + + lightBitTrailsPtr.reset(); lightTreeNodesPtr.reset(); + lsampler.upload(lightBitTrailsPtr.handle, lightTreeNodesPtr.handle); + + struct Dummy { + unsigned long long bitTrails; + unsigned long long treeNodes; + pbrt::Bounds3f bounds; + }; + + Dummy dummy = { lightBitTrailsPtr.handle, lightTreeNodesPtr.handle, lsampler.bounds() }; + + { + CUDA_CHECK( cudaMalloc(reinterpret_cast( &lightTreeDummyPtr.reset() ), sizeof( dummy )) ); + CUDA_CHECK( cudaMemcpy( + reinterpret_cast( (CUdeviceptr)lightTreeDummyPtr ), + &dummy, sizeof( dummy ), cudaMemcpyHostToDevice) ); + state.params.lightTreeSampler = lightTreeDummyPtr.handle; + } } -void optixupdatematerial(std::vector &shaders) +void optixupdatematerial(std::vector> &shaders) { camera_changed = true; @@ -2245,19 +2176,30 @@ void optixupdatematerial(std::vector &shaders) OptixUtil::rtMaterialShaders.reserve(shaders.size()); for (int i = 0; i < shaders.size(); i++) { - auto& shader_string = shaders[i].source; + auto& shader_string = shaders[i]->source; if (shader_string.empty()) zeno::log_error("shader {} is empty", i); - //OptixUtil::rtMaterialShaders.push_back(OptixUtil::rtMatShader(shaders[i].c_str(),"__closesthit__radiance", "__anyhit__shadow_cutout")); - const static std::string default_macro = "#define _SPHERE_ 0"; - const static std::string sphere_macro = "#define _SPHERE_ 1"; + auto marker = std::string("//PLACEHOLDER"); + auto marker_length = marker.length(); + + auto start_marker = shader_string.find(marker); + + if (start_marker != std::string::npos) { + auto end_marker = shader_string.find(marker, start_marker + marker_length); + + shader_string.replace(start_marker, marker_length, "/*PLACEHOLDER"); + shader_string.replace(end_marker, marker_length, "PLACEHOLDER*/"); + } + + const static std::string sphere_macro0 = "#define _SPHERE_ 0"; + const static std::string sphere_macro1 = "#define _SPHERE_ 1"; - switch(shaders[i].mark) { + switch(shaders[i]->mark) { case(ShaderMaker::Mesh): { - auto macro_pos = shader_string.find(sphere_macro); + auto macro_pos = shader_string.find(sphere_macro1); if (macro_pos != std::string::npos) { - shader_string.replace(macro_pos, sphere_macro.size(), default_macro); + shader_string.replace(macro_pos, sphere_macro1.size(), sphere_macro0); } OptixUtil::rtMaterialShaders.emplace_back(shader_string.c_str(), @@ -2267,9 +2209,9 @@ void optixupdatematerial(std::vector &shaders) } case(ShaderMaker::Sphere): { - auto macro_pos = shader_string.find(default_macro); + auto macro_pos = shader_string.find(sphere_macro0); if (macro_pos != std::string::npos) { - shader_string.replace(macro_pos, default_macro.size(), sphere_macro); + shader_string.replace(macro_pos, sphere_macro0.size(), sphere_macro1); } OptixUtil::rtMaterialShaders.emplace_back(shader_string.c_str(), @@ -2289,7 +2231,7 @@ void optixupdatematerial(std::vector &shaders) default: {} } - auto& texs = shaders[i].tex_names; + auto& texs = shaders[i]->tex_names; if(texs.size()>0){ std::cout<<"texSize:"< &shaders) printf("now compiling %d'th shader \n", i); if(OptixUtil::rtMaterialShaders[i].loadProgram(i, nullptr)==false) { - std::cout<<"program compile failed, using default"<fallback->c_str(); + //OptixUtil::rtMaterialShaders[i].m_hittingEntry = ""; + //OptixUtil::rtMaterialShaders[i].m_shadingEntry = "__closesthit__radiance"; + //OptixUtil::rtMaterialShaders[i].m_occlusionEntry = "__anyhit__shadow_cutout"; std::cout< uniqueMatsForMesh() { return result; } -static inline std::set sphere_unique_mats; - -std::set uniqueMatsForSphere() { - return sphere_unique_mats; -} - -void preload_sphere_transformed(std::string const &key, std::string const &mtlid, const std::string &instID, const glm::mat4& transform) -{ - InfoSphereTransformed dsphere; - dsphere.materialID = mtlid; - dsphere.instanceID = instID; - dsphere.optix_transform = glm::transpose(transform); - - LutSpheresTransformed[key] = dsphere; - sphere_unique_mats.insert(mtlid); -} - -void preload_sphere_crowded(std::string const &key, std::string const &mtlid, const std::string &instID, const float &radius, const zeno::vec3f ¢er) -{ - if (instID == "" || instID == "Default") { - - if (SpheresCrowded.cached.count(key) > 0) {return;} - - SpheresCrowded.cached.insert(key); - SpheresCrowded.mtlset.insert(mtlid); - - SpheresCrowded.mtlid_list.push_back(mtlid); - SpheresCrowded.instid_list.push_back(instID); - SpheresCrowded.radius_list.push_back(radius); - SpheresCrowded.center_list.push_back(center); - - } else { - - SphereInstanceGroupBase base; - base.instanceID = instID; - base.materialID = mtlid; - base.key = key; - - base.radius = radius; - base.center = center; - - SpheresInstanceGroupMap[instID] = base; - } - - sphere_unique_mats.insert(mtlid); -} - -void foreach_sphere_crowded(std::function &sbtoffset_list)> func) -{ - auto count = SpheresCrowded.center_list.size(); - - for (uint i=0; i & verts, std::vector &mat_idx, std::vector> &oMeshes, int meshesStart, int vertsStart) { @@ -2805,9 +2676,6 @@ static void updateDynamicDrawObjects() { // g_nrm.push_back(make_float4(normal[0], normal[1], normal[2],0)); // g_nrm.push_back(make_float4(normal[0], normal[1], normal[2],0)); // g_nrm.push_back(make_float4(normal[0], normal[1], normal[2],0)); -// g_clr.push_back(g_lightColor[l*3+0]); -// g_clr.push_back(g_lightColor[l*3+1]); -// g_clr.push_back(g_lightColor[l*3+2]); // g_tan.push_back(make_float4(0)); // g_tan.push_back(make_float4(0)); // g_tan.push_back(make_float4(0)); @@ -3401,7 +3269,7 @@ void set_perspective(float const *U, float const *V, float const *W, float const cam.aperture = aperture; } -void write_pfm(std::string& path, int w, int h, const float *rgb) { +static void write_pfm(std::string& path, int w, int h, const float *rgb) { std::string header = zeno::format("PF\n{} {}\n-1.0\n", w, h); std::vector data(header.size() + w * h * sizeof(zeno::vec3f)); memcpy(data.data(), header.data(), header.size()); @@ -3544,8 +3412,6 @@ void optixcleanup() { using namespace OptixUtil; try { CUDA_SYNC_CHECK(); - //cleanupSpheres(); - //sphereInstanceGroupAgentList.clear(); cleanupState( state ); rtMaterialShaders.clear(); @@ -3568,6 +3434,7 @@ void optixcleanup() { context .handle=0; pipeline .handle=0; ray_module .handle=0; + sphere_module .handle=0; raygen_prog_group .handle=0; radiance_miss_group .handle=0; occlusion_miss_group .handle=0; diff --git a/zenovis/xinxinoptix/optixPathTracer.h b/zenovis/xinxinoptix/optixPathTracer.h index a3e3131c44..64654bdddc 100644 --- a/zenovis/xinxinoptix/optixPathTracer.h +++ b/zenovis/xinxinoptix/optixPathTracer.h @@ -1,11 +1,11 @@ -// this part of code is modified from nvidia's optix example #pragma once -#ifndef __CUDACC_RTC__ - #include "optixVolume.h" -#else - #include "volume.h" -#endif +#include +#include + +#include "LightBounds.h" +// #include +#include enum RayType { @@ -15,26 +15,82 @@ enum RayType }; enum VisibilityMask { - NothingMask = 0u, - DefaultMatMask = 1u, - VolumeMatMask = 2u, + NothingMask = 0u, + DefaultMatMask = 1u << 0, + VolumeMatMask = 1u << 1, + LightMatMask = 1u << 2, EverythingMask = 255u }; -enum RayLaunchSource { - DefaultMatSource = 0u, - VolumeEdgeSource = 1u, - VolumeEmptySource = 1u << 1, - VolumeScatterSource = 1u << 2 -}; - -struct ParallelogramLight +struct GenericLight { - float3 corner; - float3 v1, v2; - float3 normal; + float3 T, B, N; float3 emission; - float cdf; + + zeno::LightType type {}; + zeno::LightShape shape{}; + uint8_t config = zeno::LightConfigNull; + + unsigned long long ies=0u; + cudaTextureObject_t tex{}; + union { + RectShape rect; + SphereShape sphere; + + ConeShape cone; + PointShape point; + }; + + bool isDeltaLight() { + if (type == zeno::LightType::Direction || type == zeno::LightType::IES) + return true; + else + return false; + } + + pbrt::LightBounds bounds() { + + auto Phi = dot(emission, make_float3(1.0f/3.0f)); + bool doubleSided = config & zeno::LightConfigDoubleside; + + if (this->type == zeno::LightType::IES) { + return this->cone.BoundAsLight(Phi, false); + } + + switch (this->shape) { + case zeno::LightShape::Plane: + return this->rect.BoundAsLight(Phi, doubleSided); + case zeno::LightShape::Sphere: + return this->sphere.BoundAsLight(Phi, false); + case zeno::LightShape::Point: + return this->point.BoundAsLight(Phi, false); + } + + return pbrt::LightBounds(); + } + + void setConeData(const float3& p, const float3& dir, float range, float coneAngle) { + this->cone.p = p; + this->cone.dir = dir; + this->cone.range = range; + this->cone.cosFalloffStart = cosf(coneAngle); + this->cone.cosFalloffEnd = cosf(coneAngle + __FLT_EPSILON__); + } + + void setRectData(const float3& v0, const float3& v1, const float3& v2, const float3& normal) { + this->rect.v0 = v0; + this->rect.v1 = v1; + this->rect.v2 = v2; + + this->rect.normal = normal; + this->rect.area = length( cross(v1, v2) ); + } + + void setSphereData(const float3& center, float radius) { + this->sphere.center = center; + this->sphere.radius = radius; + this->sphere.area = M_PIf * 4 * radius * radius; + } }; @@ -63,6 +119,7 @@ struct Params float3* frame_buffer_T; float3* frame_buffer_B; + float3* debug_buffer; float3* albedo_buffer; float3* normal_buffer; @@ -76,8 +133,26 @@ struct Params CameraInfo cam; - unsigned int num_lights; - ParallelogramLight *lights; + uint32_t num_lights; + GenericLight *lights; + uint32_t firstRectLightIdx; + uint32_t firstSphereLightIdx; + + unsigned long long lightTreeSampler; + + float skyLightProbablity() { + + static float DefaultSkyLightProbablity = 0.5f; + + if (sky_strength <= 0.0f) + return -0.0f; + + if (sky_texture == 0llu || skycdf == nullptr) + return -0.0f; + + return this->num_lights>0? DefaultSkyLightProbablity : 1.0f; + } + OptixTraversableHandle handle; int usingHdrSky; @@ -89,8 +164,8 @@ struct Params int2 windowCrop_max; int2 windowSpace; - int skynx; - int skyny; + uint32_t skynx; + uint32_t skyny; float envavg; float sky_rot; @@ -112,17 +187,11 @@ struct Params float sunSoftness; float elapsedTime; - bool simpleRender; - - -#if defined (__cudacc__) - const bool denoise; -#else - bool denoise; -#endif - bool show_background; + bool simpleRender :1; + bool show_background :1; + bool denoise : 1; }; diff --git a/zenovis/xinxinoptix/optixSphere.cpp b/zenovis/xinxinoptix/optixSphere.cpp new file mode 100644 index 0000000000..99138f043a --- /dev/null +++ b/zenovis/xinxinoptix/optixSphere.cpp @@ -0,0 +1,133 @@ +#include "optixSphere.h" + +namespace xinxinoptix +{ + +void preload_sphere_transformed(std::string const &key, std::string const &mtlid, const std::string &instID, const glm::mat4& transform) +{ + InfoSphereTransformed dsphere; + dsphere.materialID = mtlid; + dsphere.instanceID = instID; + dsphere.optix_transform = glm::transpose(transform); + + SphereTransformedTable[key] = dsphere; + sphere_unique_mats.insert(mtlid); +} + +void preload_sphere_instanced(std::string const &key, std::string const &mtlid, const std::string &instID, const float &radius, const zeno::vec3f ¢er) +{ + SphereInstanceGroupBase base; + base.instanceID = instID; + base.materialID = mtlid; + base.key = key; + + base.radius = radius; + base.center = center; + + SpheresInstanceGroupMap[instID] = base; + + sphere_unique_mats.insert(mtlid); +} + +void buildUniformedSphereGAS(const OptixDeviceContext& context, OptixTraversableHandle& gas_handle, raii& d_gas_output_buffer) +{ + OptixAccelBuildOptions accel_options{}; + accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; + accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION | + OPTIX_BUILD_FLAG_ALLOW_RANDOM_VERTEX_ACCESS | + OPTIX_BUILD_FLAG_ALLOW_RANDOM_INSTANCE_ACCESS; + + float3 sphereVertex = make_float3( 0.f, 0.f, 0.f ); + float sphereRadius = 1.0f; + + CUdeviceptr d_vertex_buffer{}; + CUDA_CHECK( cudaMalloc( reinterpret_cast( &d_vertex_buffer ), sizeof( float3 ) ) ); + CUDA_CHECK( cudaMemcpy( reinterpret_cast( d_vertex_buffer ), &sphereVertex, + sizeof( float3 ), cudaMemcpyHostToDevice ) ); + + CUdeviceptr d_radius_buffer{}; + CUDA_CHECK( cudaMalloc( reinterpret_cast( &d_radius_buffer ), sizeof( float ) ) ); + CUDA_CHECK( cudaMemcpy( reinterpret_cast( d_radius_buffer ), &sphereRadius, sizeof( float ), + cudaMemcpyHostToDevice ) ); + + OptixBuildInput sphere_input{}; + + sphere_input.type = OPTIX_BUILD_INPUT_TYPE_SPHERES; + sphere_input.sphereArray.numVertices = 1; + sphere_input.sphereArray.vertexBuffers = &d_vertex_buffer; + sphere_input.sphereArray.radiusBuffers = &d_radius_buffer; + + sphere_input.sphereArray.primitiveIndexOffset = 0; + + uint32_t sphere_input_flags[1] = {OPTIX_GEOMETRY_FLAG_REQUIRE_SINGLE_ANYHIT_CALL}; + sphere_input.sphereArray.flags = sphere_input_flags; + sphere_input.sphereArray.numSbtRecords = 1; + + buildXAS(context, accel_options, sphere_input, d_gas_output_buffer, gas_handle); + + CUDA_CHECK( cudaFree( (void*)d_vertex_buffer ) ); + CUDA_CHECK( cudaFree( (void*)d_radius_buffer ) ); +} + +void buildInstancedSpheresGAS(const OptixDeviceContext &context, std::vector>& agentList) { + + OptixAccelBuildOptions accel_options{}; + accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; + accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION | + OPTIX_BUILD_FLAG_ALLOW_RANDOM_VERTEX_ACCESS | + OPTIX_BUILD_FLAG_ALLOW_RANDOM_INSTANCE_ACCESS; + + raii _vertex_buffer; + raii _radius_buffer; + + for (auto &sphereAgent : agentList) { + + const auto sphere_count = sphereAgent->center_list.size(); + if (sphere_count == 0) continue; + + { + auto data_length = sizeof( zeno::vec3f ) * sphere_count; + + CUDA_CHECK( cudaMalloc( reinterpret_cast( &_vertex_buffer ), data_length) ); + CUDA_CHECK( cudaMemcpy( reinterpret_cast( (CUdeviceptr)_vertex_buffer ), sphereAgent->center_list.data(), + data_length, cudaMemcpyHostToDevice ) ); + } + + { + auto data_length = sizeof( float ) * sphere_count; + + CUDA_CHECK( cudaMalloc( reinterpret_cast( &_radius_buffer ), data_length) ); + CUDA_CHECK( cudaMemcpy( reinterpret_cast( (CUdeviceptr)_radius_buffer ), sphereAgent->radius_list.data(), + data_length, cudaMemcpyHostToDevice ) ); + } + + OptixBuildInput sphere_input{}; + + sphere_input.type = OPTIX_BUILD_INPUT_TYPE_SPHERES; + sphere_input.sphereArray.numVertices = sphere_count; + sphere_input.sphereArray.vertexBuffers = &_vertex_buffer; + sphere_input.sphereArray.radiusBuffers = &_radius_buffer; + //sphere_input.sphereArray.singleRadius = false; + //sphere_input.sphereArray.vertexStrideInBytes = 12; + //sphere_input.sphereArray.radiusStrideInBytes = 4; + + uint32_t sphere_input_flags[1] = {OPTIX_GEOMETRY_FLAG_REQUIRE_SINGLE_ANYHIT_CALL}; + + sphere_input.sphereArray.flags = sphere_input_flags; + sphere_input.sphereArray.numSbtRecords = 1; + sphere_input.sphereArray.sbtIndexOffsetBuffer = 0; + sphere_input.sphereArray.sbtIndexOffsetSizeInBytes = 0; + sphere_input.sphereArray.sbtIndexOffsetStrideInBytes = 0; + + std::cout << "sphere_count: " << sphere_count << std::endl; + buildXAS(context, accel_options, sphere_input, sphereAgent->inst_sphere_gas_buffer, sphereAgent->inst_sphere_gas_handle, true); + + _vertex_buffer.reset(); + _radius_buffer.reset(); + + sphereAgent->center_list.clear(); + sphereAgent->radius_list.clear(); + } +} + +} // namespace end \ No newline at end of file diff --git a/zenovis/xinxinoptix/optixSphere.h b/zenovis/xinxinoptix/optixSphere.h index 23f5afc51a..7224d37ee8 100644 --- a/zenovis/xinxinoptix/optixSphere.h +++ b/zenovis/xinxinoptix/optixSphere.h @@ -1,127 +1,97 @@ -#include +#pragma once #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "XAS.h" #include "raiicuda.h" -#include "xinxinoptixapi.h" namespace xinxinoptix { -inline void updateSphereGAS(const OptixDeviceContext& context, OptixBuildInput& sphere_input, OptixAccelBuildOptions& accel_options, - raii& sphere_gas_buffer, OptixTraversableHandle& sphere_gas_handle) -{ - OptixAccelBufferSizes gas_buffer_sizes{}; - OPTIX_CHECK( optixAccelComputeMemoryUsage( context, &accel_options, &sphere_input, 1, &gas_buffer_sizes ) ); - - size_t temp_buffer_size = roundUp(gas_buffer_sizes.tempSizeInBytes, 8u); - size_t output_buffer_size = roundUp( gas_buffer_sizes.outputSizeInBytes, 8u ); +struct InfoSphereTransformed { + std::string materialID; + std::string instanceID; - raii d_temp_buffer_gas {}; - CUDA_CHECK( cudaMalloc( reinterpret_cast( &d_temp_buffer_gas ), temp_buffer_size)); - - printf("Requires %lu MB tmp buffer and %lu MB output buffer for sphere GAS \n", temp_buffer_size / (1024 * 1024), output_buffer_size / (1024 * 1024)); - - const bool COMPACTION = accel_options.buildFlags & OPTIX_BUILD_FLAG_ALLOW_COMPACTION; - - if (!COMPACTION) { - - auto& output_buffer_gas = sphere_gas_buffer.reset(); - CUDA_CHECK( cudaMalloc( reinterpret_cast( &output_buffer_gas ), output_buffer_size) ); - - OPTIX_CHECK( optixAccelBuild( context, - nullptr, // CUDA stream - &accel_options, &sphere_input, - 1, // num build inputs - d_temp_buffer_gas, - gas_buffer_sizes.tempSizeInBytes, - output_buffer_gas, - gas_buffer_sizes.outputSizeInBytes, - &sphere_gas_handle, - nullptr, - 0 ) ); - } else { - - sphere_gas_buffer.reset(); - - raii output_buffer_gas {}; - CUDA_CHECK( cudaMalloc( reinterpret_cast( &output_buffer_gas ), output_buffer_size + sizeof(size_t)) ); - - OptixAccelEmitDesc emitProperty {}; - emitProperty.type = OPTIX_PROPERTY_TYPE_COMPACTED_SIZE; - emitProperty.result = ( CUdeviceptr )( (char*)(CUdeviceptr)output_buffer_gas.handle + output_buffer_size ); - - OPTIX_CHECK( optixAccelBuild( context, - 0, // CUDA stream - &accel_options, &sphere_input, - 1, // num build inputs - d_temp_buffer_gas, - gas_buffer_sizes.tempSizeInBytes, - output_buffer_gas, - gas_buffer_sizes.outputSizeInBytes, - &sphere_gas_handle, - &emitProperty, // emitted property list - 1 // num emitted properties - ) ); - - size_t compacted_gas_size{}; - CUDA_CHECK( cudaMemcpy( &compacted_gas_size, (void*)emitProperty.result, sizeof( size_t ), cudaMemcpyDeviceToHost ) ); - - if( compacted_gas_size < gas_buffer_sizes.outputSizeInBytes ) - { - CUDA_CHECK( cudaMalloc( reinterpret_cast( &sphere_gas_buffer ), compacted_gas_size ) ); - // use handle as input and output - OPTIX_CHECK( optixAccelCompact( context, 0, - sphere_gas_handle, - sphere_gas_buffer, - compacted_gas_size, &sphere_gas_handle ) ); - } - else - { - sphere_gas_buffer = std::move(output_buffer_gas); - } - } + glm::mat4 optix_transform; +}; + +inline std::map SphereTransformedTable; +void preload_sphere_transformed(std::string const &key, std::string const &mtlid, const std::string &instID, const glm::mat4& transform); + +struct SphereInstanceGroupBase { + std::string key; + std::string instanceID; + std::string materialID; + + zeno::vec3f center{}; + float radius{}; +}; + +inline std::map SpheresInstanceGroupMap; +void preload_sphere_instanced(std::string const &key, std::string const &mtlid, const std::string &instID, const float &radius, const zeno::vec3f ¢er); + +inline std::set sphere_unique_mats; +inline std::set uniqueMatsForSphere() { + return sphere_unique_mats; } -inline void makeUniformSphereGAS(const OptixDeviceContext& context, OptixTraversableHandle& gas_handle, raii& d_gas_output_buffer) -{ - OptixAccelBuildOptions accel_options{}; - accel_options.buildFlags = OPTIX_BUILD_FLAG_ALLOW_COMPACTION | OPTIX_BUILD_FLAG_ALLOW_RANDOM_VERTEX_ACCESS; - accel_options.operation = OPTIX_BUILD_OPERATION_BUILD; +inline OptixTraversableHandle uniformed_sphere_gas_handle {}; +inline raii uniformed_sphere_gas_buffer {}; + +void buildUniformedSphereGAS(const OptixDeviceContext& context, OptixTraversableHandle& gas_handle, raii& d_gas_output_buffer); + +struct SphereInstanceAgent { + SphereInstanceGroupBase base{}; - float3 sphereVertex = make_float3( 0.f, 0.f, 0.f ); - float sphereRadius = 1.0f; + std::vector radius_list{}; + std::vector center_list{}; - CUdeviceptr d_vertex_buffer{}; - CUDA_CHECK( cudaMalloc( reinterpret_cast( &d_vertex_buffer ), sizeof( float3 ) ) ); - CUDA_CHECK( cudaMemcpy( reinterpret_cast( d_vertex_buffer ), &sphereVertex, - sizeof( float3 ), cudaMemcpyHostToDevice ) ); + raii inst_sphere_gas_buffer {}; + OptixTraversableHandle inst_sphere_gas_handle {}; - CUdeviceptr d_radius_buffer{}; - CUDA_CHECK( cudaMalloc( reinterpret_cast( &d_radius_buffer ), sizeof( float ) ) ); - CUDA_CHECK( cudaMemcpy( reinterpret_cast( d_radius_buffer ), &sphereRadius, sizeof( float ), - cudaMemcpyHostToDevice ) ); + SphereInstanceAgent(SphereInstanceGroupBase _base):base(_base){} + //SphereInstanceAgent(SphereInstanceBase &_base):base(_base){} - OptixBuildInput sphere_input{}; + ~SphereInstanceAgent() { + inst_sphere_gas_handle = 0; + inst_sphere_gas_buffer.reset(); + } +}; + +inline std::vector> sphereInstanceGroupAgentList; +void buildInstancedSpheresGAS(const OptixDeviceContext &context, std::vector>& agentList); - sphere_input.type = OPTIX_BUILD_INPUT_TYPE_SPHERES; - sphere_input.sphereArray.numVertices = 1; - sphere_input.sphereArray.vertexBuffers = &d_vertex_buffer; - sphere_input.sphereArray.radiusBuffers = &d_radius_buffer; +void updateSphereXAS(); - sphere_input.sphereArray.primitiveIndexOffset = 0; +inline OptixTraversableHandle sphereHandleXAS {}; +inline raii sphereBufferXAS {}; + +inline void cleanupSpheresCPU() { + sphere_unique_mats.clear(); + SphereTransformedTable.clear(); + SpheresInstanceGroupMap.clear(); +} - uint32_t sphere_input_flags[1] = {OPTIX_GEOMETRY_FLAG_REQUIRE_SINGLE_ANYHIT_CALL}; - sphere_input.sphereArray.flags = sphere_input_flags; - sphere_input.sphereArray.numSbtRecords = 1; +inline void cleanupSpheresGPU() { + uniformed_sphere_gas_buffer.reset(); + uniformed_sphere_gas_handle = 0llu; - updateSphereGAS(context, sphere_input, accel_options, d_gas_output_buffer, gas_handle); + sphereInstanceGroupAgentList.clear(); - CUDA_CHECK( cudaFree( (void*)d_vertex_buffer ) ); - CUDA_CHECK( cudaFree( (void*)d_radius_buffer ) ); + sphereBufferXAS.reset(); + sphereHandleXAS = 0llu; } } // NAMESPACE END \ No newline at end of file diff --git a/zenovis/xinxinoptix/volume.cu b/zenovis/xinxinoptix/volume.cu index 8deb697630..75a716a0bb 100644 --- a/zenovis/xinxinoptix/volume.cu +++ b/zenovis/xinxinoptix/volume.cu @@ -1,28 +1,31 @@ +#include "Light.h" #include "volume.h" #include "TraceStuff.h" - -#include "DisneyBRDF.h" -#include "DisneyBSDF.h" #include "zxxglslvec.h" -#include "proceduralSky.h" +#include "math_constants.h" // #include // #include "nvfunctional" -#include #include #include #include #include +enum struct VolumeEmissionScalerType { + Raw, Density, Absorption +}; + //PLACEHOLDER static const int _vol_depth = 99; static const float _vol_extinction = 1.0f; using DataTypeNVDB0 = nanovdb::Fp32; using GridTypeNVDB0 = nanovdb::NanoGrid; +#define VolumeEmissionScaler VolumeEmissionScalerType::Raw //PLACEHOLDER -#define USING_VDB 1 +#define _USING_NANOVDB_ true +#define _DELTA_TRACKING_ true //COMMON_CODE /* w0, w1, w2, and w3 are the four cubic B-spline basis functions. */ @@ -106,18 +109,30 @@ inline __device__ float nanoSampling(Acc& acc, nanovdb::Vec3f& point_indexd) { using GridTypeNVDB = nanovdb::NanoGrid; + if constexpr(3 > Order) { + using Sampler = nanovdb::SampleFromVoxels; + return Sampler(acc)(point_indexd); + } + if constexpr(3 == Order) { nanovdb::SampleFromVoxels s(acc); return interp_tricubic_nanovdb(s, point_indexd[0], point_indexd[1], point_indexd[2]); - } else { - using Sampler = nanovdb::SampleFromVoxels; - return Sampler(acc)(point_indexd); + } + + if constexpr(4 == Order) { + RadiancePRD* prd = getPRD(); + auto uuu = nanovdb::Vec3f(prd->rndf(), prd->rndf(), prd->rndf()); + uuu -= nanovdb::Vec3f(0.5f); + auto pick = nanovdb::RoundDown(point_indexd + uuu); + auto coord = nanovdb::Coord(pick[0], pick[1], pick[2]); + return acc.getValue(coord); } - //nanovdb::BaseStencil - //auto bs = nanovdb::BoxStencil(grid); + + return 0.0f; // auto point_floor = nanovdb::RoundDown(point_indexd); // auto point_a = nanovdb::Coord(point_floor[0], point_floor[1], point_floor[2]); + // auto delta = point_indexd - point_floor; // auto value_000 = acc.getValue(point_a); // auto value_100 = acc.getValue(point_a + nanovdb::Coord(1, 0, 0)); @@ -128,8 +143,6 @@ inline __device__ float nanoSampling(Acc& acc, nanovdb::Vec3f& point_indexd) { // auto value_011 = acc.getValue(point_a + nanovdb::Coord(0, 1, 1)); // auto value_111 = acc.getValue(point_a + nanovdb::Coord(1, 1, 1)); - // auto delta = point_indexd - point_floor; - // auto value_00 = _LERP_(delta[0], value_000, value_100); // auto value_10 = _LERP_(delta[0], value_010, value_110); // auto value_01 = _LERP_(delta[0], value_001, value_101); @@ -225,7 +238,7 @@ static __inline__ __device__ vec2 samplingVDB(const unsigned long long grid_ptr, return vec2 { nanoSampling(_acc, pos_indexed), _grid->tree().root().maximum() }; } -static __inline__ __device__ VolumeOut evalVolume(float4* uniforms, VolumeIn &attrs) { +static __inline__ __device__ VolumeOut evalVolume(float4* uniforms, VolumeIn &attrs, RadiancePRD &prd) { auto att_pos = attrs.pos; auto att_clr = vec3(0); @@ -246,15 +259,15 @@ static __inline__ __device__ VolumeOut evalVolume(float4* uniforms, VolumeIn &at vec3 vol_sample_albedo = vec3(0.5f); //GENERATED_END_MARK -#if USING_VDB +#if _USING_NANOVDB_ VolumeOut output; output.albedo = clamp(vol_sample_albedo, 0.0f, 1.0f); - output.anisotropy = clamp(vol_sample_anisotropy, -0.99f, 0.99f); + output.anisotropy = clamp(vol_sample_anisotropy, -1.0f, 1.0f); //clamp(vol_sample_anisotropy, -0.99999f, 0.99999f); output.density = clamp(vol_sample_density, 0.0f, 1.0f); - output.emission = vol_sample_emission; + output.emission = max(vol_sample_emission, vec3(0.0f)); return output; #else @@ -337,12 +350,11 @@ inline __device__ float transmittanceHDDA( return transmittance; } - extern "C" __global__ void __intersection__volume() { const auto* sbt_data = reinterpret_cast( optixGetSbtDataPointer() ); const auto* grid = reinterpret_cast( sbt_data->vdb_grids[0] ); - assert( grid ); + if ( grid == nullptr) { return; } const float3 ray_orig = optixGetWorldRayOrigin(); //optixGetObjectRayOrigin(); const float3 ray_dir = optixGetWorldRayDirection(); //optixGetObjectRayDirection(); @@ -380,15 +392,15 @@ extern "C" __global__ void __closesthit__radiance_volume() //if(prd->test_distance) { return; } prd->countEmitted = false; - prd->radiance = make_float3(0); + prd->radiance = vec3(0); - prd->trace_tmin = 0; + prd->_tmin_ = 0; prd->_mask_ = EverythingMask; const HitGroupData* sbt_data = reinterpret_cast( optixGetSbtDataPointer() ); - float3 ray_orig = optixGetWorldRayOrigin(); - float3 ray_dir = optixGetWorldRayDirection(); + const float3 ray_orig = optixGetWorldRayOrigin(); + const float3 ray_dir = optixGetWorldRayDirection(); float t0 = prd->vol_t0; // world space float t1 = prd->vol_t1; // world space @@ -398,14 +410,10 @@ extern "C" __global__ void __closesthit__radiance_volume() testPRD.test_distance = true; testPRD.isSS = false; testPRD.opacity = 0.0f; - traceRadianceMasked( - params.handle, - ray_orig, - ray_dir, - 0, - _FLT_MAX_, - DefaultMatMask, - &testPRD); + + uint16_t _mask_ = EverythingMask ^ VolumeMatMask; + + traceRadiance(params.handle, ray_orig,ray_dir, 0, _FLT_MAX_, &testPRD, _mask_); if(testPRD.vol_t1 < t1) { @@ -416,7 +424,7 @@ extern "C" __global__ void __closesthit__radiance_volume() const float t_max = fmax(0.f, t1 - t0); // world space float t_ele = 0; - auto test_point = ray_orig; + float3 new_orig = ray_orig; float3 emitting = make_float3(0.0); float3 scattering = make_float3(1.0); @@ -424,240 +432,111 @@ extern "C" __global__ void __closesthit__radiance_volume() float v_density = 0.0; VolumeOut vol_out; - -#if (!_DELTA_TRACKING_) - - test_point = ray_orig + test_t * ray_dir; - auto test_point_indexd = grid->worldToIndexF(reinterpret_cast(test_point)); - v_density = linearSampling(acc, test_point_indexd); - - vec3 new_dir = ray_dir; - - if(v_density > 0){ - const auto ray = nanovdb::Ray( reinterpret_cast( ray_orig ), - reinterpret_cast( ray_dir ) ); - auto start = grid->worldToIndexF( ray( t0 ) ); - auto end = grid->worldToIndexF( ray( test_t ) ); - - auto bbox = grid->indexBBox(); - confine( bbox, start, end ); - - const float opacity = sbt_data->opacityHDDA; - - //scattering *= transmittanceHDDA( start, end, acc, 0.01 );; - new_dir = DisneyBSDF::SampleScatterDirection(prd->seed); - - pbrt::HenyeyGreenstein hg {sbt_data->greenstein}; - float3 new_dir; float2 uu = {rnd(prd->seed), rnd(prd->seed)}; - auto pdf = hg.Sample_p(-ray_dir, new_dir, uu); - // //scattering *= pdf; - - scattering *= sbt_data->colorVDB; - ray_dir = (prd->volumeHitSurface )? ray_dir : float3(new_dir); - } - -#else + auto new_dir = ray_dir; auto level = _vol_depth; + auto step_scale = 1.0f/sigma_t; + while(--level > 0) { - auto prob = rnd(prd->seed); - t_ele -= log(1.0f-prob) / (sigma_t); + auto prob = prd->rndf(); + t_ele -= logf(1.0f-prob) * step_scale; if (t_ele >= t_max) { if (prd->surface_inside_vdb) { // Hit other material - prd->_mask_ = DefaultMatMask; - prd->trace_tmin = 0; + prd->_mask_ = _mask_; + prd->_tmin_ = 0; - test_point = ray_orig; + new_orig = ray_orig; } else { // Volume edge prd->_mask_ = EverythingMask; - prd->trace_tmin = 1e-5f; + prd->_tmin_ = 1e-5f; - test_point = ray_orig + t1 * ray_dir; - test_point = rtgems::offset_ray(test_point, ray_dir); + new_orig = ray_orig + t1 * ray_dir; + new_orig = rtgems::offset_ray(new_orig, ray_dir); } v_density = 0; break; } // over shoot, outside of volume - test_point = ray_orig + (t0+t_ele) * ray_dir; + new_orig = ray_orig + (t0+t_ele) * ray_dir; - VolumeIn vol_in { test_point }; + VolumeIn vol_in { new_orig }; - vol_out = evalVolume(sbt_data->uniforms, vol_in); + vol_out = evalVolume(sbt_data->uniforms, vol_in, *prd); v_density = vol_out.density; - - float s_prob = vol_out.density; - float n_prob = 1.0f - s_prob; - - float3 s_prob_rgb = vol_out.albedo; - float3 a_prob_rgb = 1.0f - s_prob_rgb; - float3 n_prob_rgb = ( n_prob/s_prob ) * s_prob_rgb; - float3 _prob_rgb = n_prob_rgb + a_prob_rgb + s_prob_rgb; - - float3 le = vol_out.emission; - - if ( length(le) > 0.0f ) { - //float3 emission_prob = a_prob_rgb / _prob_rgb; // scale by emission prob - //le *= emission_prob; - emitting += le; + if constexpr(VolumeEmissionScaler == VolumeEmissionScalerType::Raw) { + emitting += vol_out.emission; + } else if constexpr(VolumeEmissionScaler == VolumeEmissionScalerType::Density) { + emitting += vol_out.density * vol_out.emission; + } else if constexpr(VolumeEmissionScaler == VolumeEmissionScalerType::Absorption) { + + float sigma_a = sigma_t * vol_out.density * average(1.0f - vol_out.albedo); + sigma_a = fmaxf(sigma_a, 0.0f); + auto tmp = vol_out.emission * sigma_a; + step_scale = 1.0f / fmaxf(sigma_t, average(tmp)); + emitting += tmp / sigma_t; + } + + if (prd->rndf() > v_density) { // null scattering + v_density = 0.0f; continue; } - if (rnd(prd->seed) < v_density) { - - float3 new_dir; - pbrt::HenyeyGreenstein hg { vol_out.anisotropy }; - - float2 uu = {rnd(prd->seed), rnd(prd->seed)}; - auto prob = hg.Sample_p(-ray_dir, new_dir, uu); - //auto relative_prob = prob * (CUDART_PI_F * 4); - new_dir = normalize(new_dir); - if (prd->trace_denoise_normal) { - prd->tmp_normal = 0.5f * (-ray_dir + new_dir); - } - ray_dir = new_dir; + pbrt::HenyeyGreenstein hg { vol_out.anisotropy }; + float2 uu = { prd->rndf(), prd->rndf() }; + auto _ = hg.sample(-ray_dir, new_dir, uu); + //auto relative_prob = prob * (CUDART_PI_F * 4); + new_dir = normalize(new_dir); + scattering = vol_out.albedo; + + if (prd->trace_denoise_normal) { + prd->tmp_normal = normalize(-ray_dir + new_dir); + } + if(prd->trace_denoise_albedo) { + prd->tmp_albedo = vol_out.albedo; + } - if(prd->trace_denoise_albedo) { - prd->tmp_albedo = vol_out.albedo; - } - scattering = s_prob_rgb * (_prob_rgb - a_prob_rgb) / _prob_rgb; // scattering prob - break; - } else { - v_density = 0; - } + break; } -#endif // _DELTA_TRACKING_ - prd->updateAttenuation(scattering); - ray_orig = test_point; - prd->origin = ray_orig; - prd->direction = ray_dir; + prd->origin = new_orig; + prd->direction = new_dir; prd->emission = emitting; + prd->geometryNormal = {}; //(new_dir + -ray_dir) / 2.0f; if (v_density == 0) { - prd->CH = 0.0; //prd->depth += 0; prd->radiance += prd->emission; return; } - float3 light_attenuation = make_float3(1.0f); - float pl = rnd(prd->seed); - float sum = 0.0f; - for(int lidx=0;lidxseed; - shadow_prd.nonThinTransHit = 0; - shadow_prd.shadowAttanuation = make_float3(1.0f); + shadow_prd.shadowAttanuation = vec3(1.0f); - scattering = vol_out.albedo; - - if(rnd(prd->seed)<=0.5f) { - bool computed = false; - float ppl = 0; - for (int lidx = 0; lidx < params.num_lights && computed == false; lidx++) { - ParallelogramLight light = params.lights[lidx]; - float2 z = {rnd(prd->seed), rnd(prd->seed) }; - const float z1 = z.x; - const float z2 = z.y; - float3 light_tpos = light.corner + light.v1 * 0.5f + light.v2 * 0.5f; - float3 light_pos = light.corner + light.v1 * z1 + light.v2 * z2; - - // Calculate properties of light sample (for area based pdf) - float tLdist = length(light_tpos - test_point); - float3 tL = normalize(light_tpos - test_point); - float tnDl = 1.0f; //clamp(dot(N, tL), 0.0f, 1.0f); - float tLnDl = clamp(-dot(light.normal, tL), 0.000001f, 1.0f); - float tA = length(cross(params.lights[lidx].v1, params.lights[lidx].v2)); - ppl += length(light.emission) * tnDl * tLnDl * tA / (M_PIf * tLdist * tLdist) / sum; - if (ppl > pl) { - float Ldist = length(light_pos - test_point) + 1e-6f; - float3 L = normalize(light_pos - test_point); - float nDl = 1.0f; //clamp(dot(N, L), 0.0f, 1.0f); - float LnDl = clamp(-dot(light.normal, L), 0.0f, 1.0f); - float A = length(cross(params.lights[lidx].v1, params.lights[lidx].v2)); - float weight = 0.0f; - if (nDl > 0.0f && LnDl > 0.0f) { - - traceOcclusion(params.handle, test_point, L, - 0, // tmin - Ldist - 1e-5f, // tmax, - &shadow_prd); - - light_attenuation = shadow_prd.shadowAttanuation; - - weight = sum * nDl / tnDl * LnDl / tLnDl * (tLdist * tLdist) / (Ldist * Ldist) / - (length(light.emission)+1e-6f); - } - // prd->LP = test_point; - // prd->Ldir = L; - // prd->Lweight = weight; - // prd->nonThinTransHit = 0; - - pbrt::HenyeyGreenstein hg { vol_out.anisotropy }; - float ray_prob = hg.p(-ray_dir, L); - float3 lbrdf = scattering * ray_prob; - - prd->radiance = light_attenuation * weight * 2.0f * light.emission * lbrdf; - computed = true; - } - } - } else { - - vec3 sunLightDir = vec3(params.sunLightDirX, params.sunLightDirY, params.sunLightDirZ); - auto sun_dir = BRDFBasics::halfPlaneSample(prd->seed, sunLightDir, - params.sunSoftness * 0.2f); //perturb the sun to have some softness - sun_dir = normalize(sun_dir); - // prd->LP = test_point; - // prd->Ldir = sun_dir; - // prd->Lweight = 1.0; - // prd->nonThinTransHit = 1; - traceOcclusion(params.handle, test_point, sun_dir, - 0, // tmin - 1e16f, // tmax, - &shadow_prd); - - light_attenuation = shadow_prd.shadowAttanuation; + auto evalBxDF = [&](const float3& _wi_, const float3& _wo_, float& thisPDF, vec3 illum = vec3(1.0f)) -> float3 { pbrt::HenyeyGreenstein hg { vol_out.anisotropy }; - float ray_prob = hg.p(-ray_dir, sun_dir); - float3 lbrdf = scattering * clamp(ray_prob, 0.0f, 1.0f); + thisPDF = hg.p(_wo_, _wi_); + return scattering * thisPDF; + }; - float tmpPdf; - auto illum = float3(envSky(sun_dir, sunLightDir, make_float3(0., 0., 1.), - 40, // be careful - .45, 15., 1.030725f * 0.3f, params.elapsedTime, tmpPdf)); - - prd->radiance = light_attenuation * params.sunLightIntensity * 2.0f * lbrdf * illum; - } - - prd->CH = 1.0; + DirectLighting(prd, shadow_prd, new_orig, ray_dir, evalBxDF); + prd->depth += 1; prd->radiance += prd->emission; - + return; } @@ -680,28 +559,10 @@ extern "C" __global__ void __anyhit__occlusion_volume() const float sigma_t = _vol_extinction; -#if (!_DELTA_TRACKING_) - - const auto ray = nanovdb::Ray( reinterpret_cast( ray_orig ), - reinterpret_cast( ray_dir ) ); - auto start = grid->worldToIndexF( ray( t0 ) ); - auto end = grid->worldToIndexF( ray( t1 ) ); - - auto bbox = grid->indexBBox(); - confine( bbox, start, end ); - - const float opacity = sbt_data->opacityHDDA; - float transHDDA = transmittanceHDDA( start, end, acc, sbt_data->opacityHDDA ); - if (transHDDA < 1.0) { - transmittance *= transHDDA; - transmittance *= sbt_data->colorVDB; - } - -#else auto level = _vol_depth; while(--level > 0) { - auto prob = rnd(prd->seed); + auto prob = prd->rndf(); t_ele -= log(1.0f-prob) / (sigma_t); test_point = ray_orig + (t0+t_ele) * ray_dir; @@ -711,26 +572,34 @@ extern "C" __global__ void __anyhit__occlusion_volume() } // over shoot, outside of volume VolumeIn vol_in { test_point }; - VolumeOut vol_out = evalVolume(sbt_data->uniforms, vol_in); + VolumeOut vol_out = evalVolume(sbt_data->uniforms, vol_in, *prd); const auto v_density = vol_out.density; - transmittance *= 1.0f - clamp(v_density, 0.0f, 1.0f); + auto prob_scatter = clamp(v_density, 0.0f, 1.0f); + auto prob_nulling = 1.0f - prob_scatter; + + pbrt::HenyeyGreenstein hg { vol_out.anisotropy }; + auto prob_continue = hg.p(-ray_dir, ray_dir) * prob_scatter; + prob_continue = clamp(prob_continue, 0.0, 1.0f); + //printf("prob_continue %f \n", prob_continue); + + auto tr = transmittance * prob_nulling; + tr += transmittance * prob_continue * vol_out.albedo; + + transmittance = clamp(tr, 0.0, 1.0f); + auto avg = dot(transmittance, make_float3(1.0f/3.0f)); if (avg < 0.1f) { float q = fmax(0.05f, 1 - avg); - if (rnd(prd->seed) < q) { + if (prd->rndf() < q) { transmittance = vec3(0); break; } else { transmittance /= 1-q; } } - if (v_density > 0) { - transmittance *= vol_out.albedo; - } } -#endif prd->shadowAttanuation *= transmittance; optixIgnoreIntersection(); diff --git a/zenovis/xinxinoptix/volume.h b/zenovis/xinxinoptix/volume.h index 01894998c0..7988336e1d 100644 --- a/zenovis/xinxinoptix/volume.h +++ b/zenovis/xinxinoptix/volume.h @@ -1,75 +1,58 @@ #pragma once -#include +#include -#define _DELTA_TRACKING_ true - -#ifdef __CUDACC_RTC__ -#else +#ifndef __CUDACC_RTC__ +#include #endif -#include - -#include -#include -#include - namespace nanovdb { using Fp32 = float; }; namespace pbrt { -__device__ -inline void CoordinateSystem(const float3& a, float3& b, float3& c) { - -// if (abs(a.x) > abs(a.y)) -// b = float3{-a.z, 0, a.x} / -// sqrt(max(_FLT_EPL_, a.x * a.x + a.z * a.z)); -// else -// b = float3{0, a.z, -a.y} / -// sqrt(max(_FLT_EPL_, a.y * a.y + a.z * a.z)); - - if (fabs(a.x) > fabs(a.y)) - b = float3{-a.z, 0, a.x}; - else - b = float3{0, a.z, -a.y}; - - b = normalize(b); - c = cross(a, b); -} - -inline float3 SphericalDirection(float sinTheta, float cosTheta, float phi) { - return float3{sinTheta * cosf(phi), sinTheta * sinf(phi), cosTheta}; -} - -inline float3 SphericalDirection(float sinTheta, float cosTheta, float phi, - const float3 &x, const float3 &y, const float3 &z) { - return sinTheta * cosf(phi) * x + sinTheta * sinf(phi) * y + cosTheta * z; -} - struct HenyeyGreenstein { float g; __device__ HenyeyGreenstein(float g) : g(g) {} float p(const float3 &wo, const float3 &wi) const; - float Sample_p(const float3 &wo, float3 &wi, const float2 &uu) const; + float sample(const float3 &wo, float3 &wi, const float2 &uu) const; }; +inline float Schlick(float cosTheta, float k) +{ + return (1.0f - k * k) / (4.0f * M_PIf * pow(1.0f - k * cosTheta, 2.0f)); +} + // Media Inline Functions inline float PhaseHG(float cosTheta, float g) { float gg = g * g; float denom = 1 + gg + 2 * g * cosTheta; + + if (denom < __FLT_EPSILON__) { + return 1.0f; + } + return (0.25f / M_PIf) * (1 - gg) / (denom * sqrtf(denom)); } // HenyeyGreenstein Method Definitions inline float HenyeyGreenstein::p(const float3 &wo, const float3 &wi) const { return PhaseHG(dot(wo, wi), g); + + // float k = 1.55f*g - 0.55f*g*g*g; + // return Schlick(dot(wo, wi), k); } -inline float HenyeyGreenstein::Sample_p(const float3 &wo, float3 &wi, const float2 &uu) const { +inline float HenyeyGreenstein::sample(const float3 &wo, float3 &wi, const float2 &uu) const { // Compute $\cos \theta$ for Henyey--Greenstein sample + + if (fabsf(g) >= 1.0f) { + wi = copysignf(1.0f, -g) * wo; + return 1.0f; + } + float cosTheta; if (fabs(g) < 1e-3f) cosTheta = 1 - 2 * uu.x; @@ -85,6 +68,7 @@ inline float HenyeyGreenstein::Sample_p(const float3 &wo, float3 &wi, const floa float3 v1, v2; CoordinateSystem(wo, v1, v2); + //CoordinateSystem(wo, &v1, &v2); wi = SphericalDirection(sinTheta, cosTheta, phi, v1, v2, wo); return PhaseHG(cosTheta, g); diff --git a/zenovis/xinxinoptix/volume/optixVolume.cpp b/zenovis/xinxinoptix/volume/optixVolume.cpp index 738367ed57..21151934df 100644 --- a/zenovis/xinxinoptix/volume/optixVolume.cpp +++ b/zenovis/xinxinoptix/volume/optixVolume.cpp @@ -208,7 +208,7 @@ void loadVolumeVDB(VolumeWrapper& volume, const std::string& path) { std::cout << "-----------------------------------------------" << std::endl; } -void processGrid(GridWrapper& grid, const std::string& path) +static void processGrid(GridWrapper& grid, const std::string& path) { auto& gridHdl = grid.handle; diff --git a/zenovis/xinxinoptix/volume/optixVolume.h b/zenovis/xinxinoptix/volume/optixVolume.h index 43b2496557..6957f12e10 100644 --- a/zenovis/xinxinoptix/volume/optixVolume.h +++ b/zenovis/xinxinoptix/volume/optixVolume.h @@ -5,9 +5,6 @@ #include #include -#include -#include - #include #include #include diff --git a/zenovis/xinxinoptix/xinxinoptixapi.h b/zenovis/xinxinoptix/xinxinoptixapi.h index 677658383b..d3b3ad8a8f 100644 --- a/zenovis/xinxinoptix/xinxinoptixapi.h +++ b/zenovis/xinxinoptix/xinxinoptixapi.h @@ -1,12 +1,12 @@ #pragma once #include +#include #include #include #include #include -#include -#include +#include "optixSphere.h" enum ShaderMaker { Mesh = 0, @@ -16,57 +16,16 @@ enum ShaderMaker { struct ShaderPrepared { ShaderMaker mark; - std::string material; + std::string matid; std::string source; std::vector tex_names; -}; - -namespace xinxinoptix { - -struct InfoSphereTransformed { - std::string materialID; - std::string instanceID; - - glm::mat4 optix_transform; - //Draw uniform sphere with transform -}; - -inline std::map LutSpheresTransformed; -void preload_sphere_transformed(std::string const &key, std::string const &mtlid, const std::string &instID, const glm::mat4& transform); - -struct InfoSpheresCrowded { - uint32_t sbt_count = 0; - std::set cached; - std::set mtlset; - std::vector mtlid_list{}; - std::vector sbtoffset_list{}; - std::vector instid_list{}; - - std::vector radius_list{}; - std::vector center_list{}; -}; - -inline InfoSpheresCrowded SpheresCrowded; - -struct SphereInstanceGroupBase { - std::string key; - std::string instanceID; - std::string materialID; - - zeno::vec3f center{}; - float radius{}; + std::shared_ptr fallback; }; -inline std::map SpheresInstanceGroupMap; - -void preload_sphere_crowded(std::string const &key, std::string const &mtlid, const std::string &instID, const float &radius, const zeno::vec3f ¢er ); -void foreach_sphere_crowded(std::function &sbtoffset_list)> func); - -void cleanupSpheres(); +namespace xinxinoptix { std::set uniqueMatsForMesh(); -std::set uniqueMatsForSphere(); void optixcleanup(); void optixrender(int fbo = 0, int samples = 1, bool denoise = false, bool simpleRender = false); @@ -79,15 +38,14 @@ void UpdateInst(); void UpdateStaticInstMesh(const std::map &mtlidlut); void UpdateDynamicInstMesh(const std::map &mtlidlut); void CopyInstMeshToGlobalMesh(); -void UpdateGasAndIas(bool staticNeedUpdate); -void optixupdatematerial(std::vector &shaders); +void UpdateMeshGasAndIas(bool staticNeedUpdate); +void optixupdatematerial(std::vector> &shaders); -void updateCrowdedSpheresGAS(); -void updateUniformSphereGAS(); -void updateInstancedSpheresGAS(); +void updateSphereXAS(); void updateVolume(uint32_t volume_shader_offset); -void optixupdatelight(); +void buildRootIAS(); +void buildLightTree(); void optixupdateend(); void set_window_size(int nx, int ny); @@ -97,7 +55,7 @@ void load_object(std::string const &key, std::string const &mtlid, const std::st void unload_object(std::string const &key); void load_inst(const std::string &key, const std::string &instID, const std::string &onbType, std::size_t numInsts, const float *pos, const float *nrm, const float *uv, const float *clr, const float *tang); void unload_inst(const std::string &key); -void load_light(std::string const &key, float const*v0,float const*v1,float const*v2, float const*nor,float const*emi ); +void load_light(std::string const &key, float const*v0,float const*v1,float const*v2, float const*nor,float const*emi, bool visible, bool doubleside, int shape, int type, std::string& profileKey); void unload_light(); void update_procedural_sky(zeno::vec2f sunLightDir, float sunLightSoftness, zeno::vec2f windDir, float timeStart, float timeSpeed, float sunLightIntensity, float colorTemperatureMix, float colorTemperature); diff --git a/zenovis/xinxinoptix/zxxglslvec.h b/zenovis/xinxinoptix/zxxglslvec.h index 8743d32c29..af30e7e615 100644 --- a/zenovis/xinxinoptix/zxxglslvec.h +++ b/zenovis/xinxinoptix/zxxglslvec.h @@ -218,6 +218,15 @@ __forceinline__ __device__ vec4 operator*(float b, vec4 a) return vec4(a.x*b, a.y*b, a.z*b, a.w*b); } +__forceinline__ __device__ vec3 operator*(float3 b, vec3 a) +{ + return vec3(a.x*b.x, a.y*b.y, a.z*b.z); +} +__forceinline__ __device__ vec4 operator*(float4 b, vec4 a) +{ + return vec4(a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w); +} + __forceinline__ __device__ vec2 operator/(vec2 a, float b) { return vec2(a.x/b, a.y/b); @@ -510,21 +519,21 @@ __forceinline__ __device__ vec4 inversesqrt(vec4 a) //////////////begin of common math///////////////////////////////////////////////// -__forceinline__ __device__ float abs(float a) -{ - return float(fabsf(a)); -} +// __forceinline__ __device__ float abs(float a) +// { +// return float(fabsf(a)); +// } __forceinline__ __device__ vec2 abs(vec2 a) { - return vec2(abs(a.x), abs(a.y)); + return vec2(fabsf(a.x), fabsf(a.y)); } __forceinline__ __device__ vec3 abs(vec3 a) { - return vec3(abs(a.x), abs(a.y), abs(a.z)); + return vec3(fabsf(a.x), fabsf(a.y), fabsf(a.z)); } __forceinline__ __device__ vec4 abs(vec4 a) { - return vec4(abs(a.x), abs(a.y), abs(a.z), abs(a.w)); + return vec4(fabsf(a.x), fabsf(a.y), fabsf(a.z), fabsf(a.w)); } __forceinline__ __device__ float m_sign(float a) @@ -924,6 +933,25 @@ __forceinline__ __device__ float length(vec4 a) { return sqrtf(dot(a,a)); } + +template +__forceinline__ __device__ float lengthSquared(T a) +{ + return dot(a,a); +} + +__forceinline__ __device__ float average(vec2 a) +{ + return (a.x + a.y) / 2.0f; +} +__forceinline__ __device__ float average(vec3 a) +{ + return (a.x + a.y + a.z) / 3.0f; +} +__forceinline__ __device__ float average(vec4 a) +{ + return (a.x + a.y + a.z + a.w) / 4.0f; +} __forceinline__ __device__ vec2 normalize(vec2 a) { return a/(length(a)+1e-6f); @@ -1149,7 +1177,7 @@ __forceinline__ __device__ float luminance(vec3 c) { } __forceinline__ __device__ float safepower(float in1, float in2) { - return sign(in1) * pow(abs(in1), in2); + return sign(in1) * powf(abs(in1), in2); } __forceinline__ __device__ vec2 safepower(vec2 in1, vec2 in2) { @@ -1186,7 +1214,7 @@ __forceinline__ __device__ float sinTheta2(vec3 w) { } __forceinline__ __device__ float sinTheta(vec3 w) { - return sqrt(sinTheta2(w)); + return sqrtf(sinTheta2(w)); } __forceinline__ __device__ float tanTheta(vec3 w) { @@ -1230,7 +1258,7 @@ __forceinline__ __device__ vec3 refract(vec3 I, vec3 N, float eta) return vec3(0,0,0); } else - return -eta * I + (eta * dot(N, I) - sqrt(k)) * N; + return -eta * I + (eta * dot(N, I) - sqrtf(k)) * N; } __forceinline__ __device__ unsigned int laine_karras_permutation(unsigned int x, unsigned int seed) {