commit 084aaefcd0d724ac52ef3f1746b3830a46a80f29 Author: indigo Date: Fri Sep 1 03:54:36 2023 +0800 indigo Init Repo diff --git a/.env b/.env new file mode 100644 index 0000000..a9a1a92 --- /dev/null +++ b/.env @@ -0,0 +1 @@ +PYTHONPATH=C:\Autodesk\mtoa\4.2.4\2020\scripts \ No newline at end of file diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..a40b1ad --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,22 @@ +{ + "configurations": [ + { + "name": "Win32", + "includePath": [ + "${default}" + ], + "defines": [ + "_DEBUG", + "UNICODE", + "_UNICODE" + ], + "windowsSdkVersion": "10.0.18362.0", + "compilerPath": "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.28.29333/bin/Hostx64/x64/cl.exe", + "cStandard": "c17", + "cppStandard": "c++17", + "intelliSenseMode": "windows-msvc-x64", + "configurationProvider": "ms-vscode.cmake-tools" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..3a96e45 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,34 @@ +{ + //"cmake.configureEnvironment": { + // "ARNOLD_LOCATION": "D:/library/external/Arnold-5.1.1.1" + //}, + "C_Cpp.default.includePath": [ + //"D:\\library\\external\\Arnold-5.1.1.1\\include" + "C:/Program Files/Autodesk/Maya2020/plug-ins/xgen/include", + "C:/Program Files/Autodesk/Maya2020/include", + "D:/library/external/Arnold-6.2.1.1/include", + "C:/Autodesk/mtoa/4.2.4/2020/include" + ], + "C_Cpp.default.intelliSenseMode": "windows-msvc-x64", + "files.associations": { + "xstring": "cpp", + "initializer_list": "c", + "list": "c", + "map": "c", + "sstream": "c", + "unordered_map": "c", + "unordered_set": "c", + "vector": "c", + "xhash": "c", + "xmemory": "c", + "xtree": "c", + "tuple": "c", + "memory": "cpp", + "xutility": "cpp", + "utility": "cpp" + }, + "python.analysis.extraPaths": [ + "C:/Autodesk/mtoa/4.2.4/2020/scripts" + ], + "python.envFile": "${workspaceFolder}/.env" +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..dbd9493 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,40 @@ +project(apShaders) +cmake_minimum_required(VERSION 3.2) +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} + ${CMAKE_SOURCE_DIR}/cmake/modules + ${CMAKE_SOURCE_DIR}/cmake/macros) + +include(CheckCXXCompilerFlag) + +CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) +CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) + +if(WIN32) + # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W0") + add_definitions("-W3 -MP -D_CRT_SECURE_NO_WARNINGS -wd4005 -wd4996 -wd4305 -wd4244 -nologo") + add_definitions(-DPLATFORM_WINDOWS -DPLATFORM=WINDOWS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") +elseif(APPLE) + add_definitions(-DPLATFORM_DARWIN -DPLATFORM=DARWIN) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") +else() + add_definitions(-DPLATFORM_LINUX -DPLATFORM=LINUX -D_LINUX) +endif() + +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") +endif() + +if("${CMAKE_BUILD_TYPE}" MATCHES "Debug") + add_definitions(-DDEBUG=1 -UNDEBUG) +elseif("${CMAKE_BUILD_TYPE}" MATCHES "Release") + add_definitions(-DNDEBUG=1 -UDEBUG) + if(NOT WIN32) + add_definitions(-O3) + endif() +endif() + +Find_Package(Arnold) +Find_Package(Mtoa) + +add_subdirectory(src) \ No newline at end of file diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..def8cfc --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,79 @@ +{ + "version": 2, + "configurePresets": [ + { + "name": "Arnold_6.2.1.1_Maya2020", + "displayName": "Mtoa 4.2.4 for Maya 2020 (Arnold 6.2.0.1)", + "description": "Sets Visual Studio 17 2022 Win64 generator, build and install directory", + "generator": "Visual Studio 17 2022", + "toolset": "v141", + "binaryDir": "${sourceDir}/build/${presetName}", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "CMAKE_TOOLCHAIN_FILE": "", + "CMAKE_INSTALL_PREFIX": "${sourceDir}/install/2020", + "CMAKE_CXX_FLAGS_RELWITHDEBINFO": "/Od /Zi", + "CMAKE_CXX_FLAGS_RELEASE": "/O2" + }, + "environment": { + "MAYA_VERSION": "2020", + "ARNOLD_LOCATION": "D:/library/external/Arnold-6.2.1.1", + "MTOA_LOCATION":"C:/Autodesk/mtoa/4.2.4/2020" + } + }, + { + "name": "Arnold-7.1.3.2_Maya2020", + "displayName": "Mtoa 5.2.1.1 Maya 2020 (Arnold 7.1.3.2)", + "description": "Sets Visual Studio 17 2022 Win64 generator, build and install directory", + "generator": "Visual Studio 17 2022", + "toolset": "v141", + "binaryDir": "${sourceDir}/build/${presetName}", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "CMAKE_TOOLCHAIN_FILE": "", + "CMAKE_INSTALL_PREFIX": "${sourceDir}/install/2020", + "CMAKE_CXX_FLAGS_RELWITHDEBINFO": "/Od /Zi", + "CMAKE_CXX_FLAGS_RELEASE": "/O2" + }, + "environment": { + "MAYA_VERSION": "2020", + "ARNOLD_LOCATION": "D:/library/external/Arnold-7.1.3.2", + "MTOA_LOCATION":"C:/Autodesk/mtoa/5.2.1.1/2020" + } + } + ], + "buildPresets": [ + { + "name": "Arnold_6.2.0.1_Release", + "description": "Release Build", + "displayName": "Mtoa 4.2.4 (Arnold_6.2) for Maya 2020 Release", + "configurePreset": "Arnold_6.2.1.1_Maya2020", + "configuration": "Release", + "targets": "install" + }, + { + "name": "Arnold_6.2.0.1_RelWithDebInfo", + "description": "Release Build", + "displayName": "Mtoa 4.2.4 (Arnold_6.2) for Maya 2020 RelWithDebInfo", + "configurePreset": "Arnold_6.2.1.1_Maya2020", + "configuration": "RelWithDebInfo", + "targets": "install" + }, + { + "name": "Arnold_7.1.3.2_Release", + "description": "Release Build", + "displayName": "Mtoa 5.2.1.1 (Arnold_7.1) for Maya 2022 Release", + "configurePreset": "Arnold-7.1.3.2_Maya2020", + "configuration": "Release", + "targets": "install" + }, + { + "name": "Arnold_7.1.3.2_RelWithDebInfo", + "description": "Release Build", + "displayName": "Mtoa 5.2.1.1 (Arnold_7.1) for Maya 2022 RelWithDebInfo", + "configurePreset": "Arnold-7.1.3.2_Maya2020", + "configuration": "RelWithDebInfo", + "targets": "install" + } + ] +} \ No newline at end of file diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..dea48a4 --- /dev/null +++ b/build.bat @@ -0,0 +1,5 @@ +@echo off + +set ARNOLD_LOCATION=D:\library\external\Arnold-5.1.1.1 +cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_INSTALL_PREFIX=C:\workspace\apShaders\install .. +cmake --build . --target install --config Release \ No newline at end of file diff --git a/cmake/modules/FindArnold.cmake b/cmake/modules/FindArnold.cmake new file mode 100644 index 0000000..065f60f --- /dev/null +++ b/cmake/modules/FindArnold.cmake @@ -0,0 +1,108 @@ +include (FindPackageHandleStandardArgs) + +set(ARNOLD_INC_SUFFIX "include") +set(ARNOLD_LIB_SUFFIX "lib") +set(ARNOLD_PLUGIN_EXTENSION ".so") +set(ARNOLD_AI_LIB ai) +set(ARNOLD_KICK_NAME kick) + +if(WIN32) + set(ARNOLD_PLUGIN_EXTENSION ".dll") +elseif(APPLE) +else() + set(ARNOLD_LIB_SUFFIX "bin") +endif() + +if(DEFINED ENV{ARNOLD_LOCATION}) + set(ARNOLD_LOCATION $ENV{ARNOLD_LOCATION}) +endif() + +if(DEFINED ENV{ARNOLD_ROOT}) + set(ARNOLD_LOCATION $ENV{ARNOLD_ROOT}) +endif() + +string(REPLACE "\\" "/" ARNOLD_LOCATION ${ARNOLD_LOCATION}) +set(ARNOLD_ROOT ${ARNOLD_LOCATION}) + +set(ARNOLD_INCLUDE_PATH ARNOLD_INCLUDE_PATH-NOTFOUND) +find_path(ARNOLD_INCLUDE_PATH ai.h + PATHS + ${ARNOLD_ROOT} + PATH_SUFFIXES + "${ARNOLD_INC_SUFFIX}" + NO_DEFAULT_PATH + DOC "Arnold include path") + +set(ARNOLD_AI_LIBRARY ARNOLD_AI_LIBRARY-NOTFOUND) +find_library(ARNOLD_AI_LIBRARY ai + PATHS + ${ARNOLD_ROOT} + PATH_SUFFIXES + "${ARNOLD_LIB_SUFFIX}" + NO_DEFAULT_PATH + DOC "Arnold ai library") + +set(ARNOLD_LIBRARY_PATH ARNOLD_LIBRARY_PATH-NOTFOUND) + +if(ARNOLD_AI_LIBRARY) + set(ARNOLD_LIBRARY_PATH "${ARNOLD_ROOT}/${ARNOLD_LIB_SUFFIX}") +endif() + +find_program(ARNOLD_KICK + ${ARNOLD_KICK_NAME} + PATHS + "${ARNOLD_ROOT}/bin" + NO_DEFAULT_PATH + DOC "Arnold kick Path") + +set(ARNOLD_VERSION ARNOLD_VERSION-NOTFOUND) +#if(EXISTS ${ARNOLD_KICK}) +# execute_process(COMMAND "${ARNOLD_KICK}" "-av" +# WORKING_DIRECTORY "${ARNOLD_ROOT}/bin" +# RESULT_VARIABLE ARNOLD_KICK_RESULT +# OUTPUT_VARIABLE ARNOLD_VERSION) +# if(${ARNOLD_KICK_RESULT} GREATER 0) +# message(FATAL_ERROR "Fail to get arnold version : ${ARNOLD_KICK_RESULT}") +# endif() +#endif() +set(ARNOLD_VERSION_HEADER "${ARNOLD_INCLUDE_PATH}/ai_version.h") + +if(EXISTS ${ARNOLD_VERSION_HEADER}) + + file(STRINGS ${ARNOLD_VERSION_HEADER} arnold_version_str REGEX "#define AI_VERSION_ARCH_NUM ") + string(REGEX REPLACE "#define AI_VERSION_ARCH_NUM" "" AI_VERSION_ARCH_NUM "${arnold_version_str}") + string(STRIP "${AI_VERSION_ARCH_NUM}" AI_VERSION_ARCH_NUM) + + file(STRINGS ${ARNOLD_VERSION_HEADER} arnold_version_str REGEX "#define AI_VERSION_MAJOR_NUM ") + string(REGEX REPLACE "#define AI_VERSION_MAJOR_NUM" "" AI_VERSION_MAJOR_NUM "${arnold_version_str}") + string(STRIP "${AI_VERSION_MAJOR_NUM}" AI_VERSION_MAJOR_NUM) + + file(STRINGS ${ARNOLD_VERSION_HEADER} arnold_version_str REGEX "#define AI_VERSION_MINOR_NUM ") + string(REGEX REPLACE "#define AI_VERSION_MINOR_NUM" "" AI_VERSION_MINOR_NUM "${arnold_version_str}") + string(STRIP "${AI_VERSION_MINOR_NUM}" AI_VERSION_MINOR_NUM) + + file(STRINGS ${ARNOLD_VERSION_HEADER} arnold_version_str REGEX "#define AI_VERSION_FIX ") + string(REGEX REPLACE "#define AI_VERSION_FIX" "" AI_VERSION_FIX "${arnold_version_str}") + string(STRIP "${AI_VERSION_FIX}" AI_VERSION_FIX) + string(REGEX REPLACE "\"" "" AI_VERSION_FIX "${AI_VERSION_FIX}") + + unset(arnold_version_str) + set(ARNOLD_VERSION "${AI_VERSION_ARCH_NUM}.${AI_VERSION_MAJOR_NUM}.${AI_VERSION_MINOR_NUM}.${AI_VERSION_FIX}") + +endif() + +message(STATUS "ARNOLD_ROOT : ${ARNOLD_ROOT}") +message(STATUS "ARNOLD_INCLUDE_PATH : ${ARNOLD_INCLUDE_PATH}") +message(STATUS "ARNOLD_LIBRARY_PATH : ${ARNOLD_LIBRARY_PATH}") +message(STATUS "ARNOLD_AI_LIBRARY : ${ARNOLD_AI_LIBRARY}") +message(STATUS "ARNOLD_VERSION : ${ARNOLD_VERSION}") + +find_package_handle_standard_args(Arnold + REQUIRED_VARS + ARNOLD_ROOT + ARNOLD_INCLUDE_PATH + ARNOLD_LIBRARY_PATH + ARNOLD_AI_LIBRARY + VERSION_VAR + ARNOLD_VERSION + ) diff --git a/cmake/modules/FindMaya.cmake b/cmake/modules/FindMaya.cmake new file mode 100644 index 0000000..d5a76c0 --- /dev/null +++ b/cmake/modules/FindMaya.cmake @@ -0,0 +1,210 @@ +include(FindPackageHandleStandardArgs) + +if(NOT DEFINED MAYA_VERSION) + set(MAYA_VERSION 2018) +endif() + +if(DEFINED ENV{MAYA_VERSION}) + set(MAYA_VERSION $ENV{MAYA_VERSION}) +endif() + +set(MAYA_BIN_SUFFIX "bin") +set(MAYA_INC_SUFFIX "include") +set(MAYA_LIB_SUFFIX "lib") + +if(WIN32) + set(MAYA_LOCATION "$ENV{ProgramFiles}/Autodesk/Maya${MAYA_VERSION}") + set(MAYA_PLUGIN_EXT ".mll") + set(MAYA_COMPILE_FLAGS "/MD /D \"NT_PLUGIN\" /D \"REQUIRE_IOSTREAM\" /D \"_BOOL\"" ) + set(MAYA_LINK_FLAGS " /export:initializePlugin /export:uninitializePlugin " ) +elseif(APPLE) + set(MAYA_LOCATION "/Applications/Autodesk/maya${MAYA_VERSION}") + set(MAYA_PLUGIN_EXT ".bundle") + set(MAYA_COMPILE_FLAGS "-DAW_NEW_IOSTREAMS -DCC_GNU_ -DOSMac_ -DOSMacOSX_ -DOSMac_MachO_ -DREQUIRE_IOSTREAM -fno-gnu-keywords -D_LANGUAGE_C_PLUS_PLUS") + set(MAYA_LINK_FLAGS "-fno-gnu-keywords -framework System -framework SystemConfiguration -framework CoreServices -framework Carbon -framework Cocoa -framework ApplicationServices -framework Quicktime -framework IOKit -bundle -fPIC -L${ALEMBIC_MAYA_LIB_ROOT} -Wl,-executable_path,${ALEMBIC_MAYA_LIB_ROOT}") +else() + set(MAYA_LOCATION "/usr/autodesk/maya${MAYA_VERSION}") + set(MAYA_PLUGIN_EXT ".so") + set(MAYA_COMPILE_FLAGS "-m64 -g -pthread -pipe -D_BOOL -DLINUX -DLINUX_64 -DREQUIRE_IOSTREAM -fPIC -Wno-deprecated -fno-gnu-keywords") + set(MAYA_LINK_FLAGS "-shared -m64 -g -pthread -pipe -D_BOOL -DLINUX -DLINUX_64 -DREQUIRE_IOSTREAM -fPIC -Wno-deprecated -fno-gnu-keywords -Wl,-Bsymbolic") +endif() + +set(MAYA_ROOT ${MAYA_LOCATION}) +string(REPLACE "\\" "/" MAYA_ROOT ${MAYA_ROOT}) + +if(DEFINED ENV{MAYA_LOCATION}) + set(MAYA_ROOT $ENV{MAYA_LOCATION}) +endif() + +set(MAYA_EXE MAYA_EXE-NOTFOUND) +find_program(MAYA_EXE maya + PATHS + ${MAYA_ROOT} + PATH_SUFFIXES + "${MAYA_BIN_SUFFIX}" + NO_DEFAULT_PATH + DOC "Maya Executable Path") + +set(MAYA_PY_EXE MAYA_PY_EXE-NOTFOUND) +find_program(MAYA_PY_EXE mayapy + PATHS + ${MAYA_ROOT} + PATH_SUFFIXES + "${MAYA_BIN_SUFFIX}" + NO_DEFAULT_PATH + DOC "Maya Python Executable Path") + +set(MAYA_INCLUDE_PATH MAYA_INCLUDE_PATH-NOTFOUND) +find_path(MAYA_INCLUDE_PATH "maya/MFn.h" + PATHS + ${MAYA_ROOT} + PATH_SUFFIXES + "${MAYA_INC_SUFFIX}" + NO_DEFAULT_PATH + DOC "Maya Include Dir") + +set(MAYA_OPENMAYA_LIBRARY MAYA_OPENMAYA_LIBRARY-NOTFOUND) +find_library(MAYA_OPENMAYA_LIBRARY OpenMaya + PATHS + "${MAYA_ROOT}/lib" + DOC "OpenMaya Libray Path") + +if(MAYA_OPENMAYA_LIBRARY) + set(MAYA_LIBRARY_PATH "${MAYA_ROOT}/lib") +endif() + +set(MAYA_OPENMAYAFX_LIBRARY MAYA_OPENMAYAFX_LIBRARY-NOTFOUND) +find_library(MAYA_OPENMAYAFX_LIBRARY OpenMayaFX + PATHS + "${MAYA_ROOT}/lib" + DOC "OpenMayaFX Libray Path") + +set(MAYA_OPENMAYAANIM_LIBRARY MAYA_OPENMAYAANIM_LIBRARY-NOTFOUND) +find_library(MAYA_OPENMAYAANIM_LIBRARY OpenMayaAnim + PATHS + "${MAYA_ROOT}/lib" + DOC "OpenMayaAnim Libray Path") + +set(MAYA_OPENMAYAUI_LIBRARY MAYA_OPENMAYAUI_LIBRARY-NOTFOUND) +find_library(MAYA_OPENMAYAUI_LIBRARY OpenMayaUI + PATHS + "${MAYA_ROOT}/lib" + DOC "OpenMayaUI Libray Path") + +set(MAYA_OPENMAYARENDER_LIBRARY MAYA_OPENMAYARENDER_LIBRARY-NOTFOUND) +find_library(MAYA_OPENMAYARENDER_LIBRARY OpenMayaRender + PATHS + "${MAYA_ROOT}/lib" + DOC "OpenMayaRender Libray Path") + +set(MAYA_FOUNDATION_LIBRARY MAYA_FOUNDATION_LIBRARY-NOTFOUND) +find_library(MAYA_FOUNDATION_LIBRARY Foundation + PATHS + "${MAYA_ROOT}/lib" + DOC "Foundation Libray Path") + +set(XGEN_PLUGIN "plug-ins/xgen") + +set(MAYA_XGEN_ROOT MAYA_XGEN_ROOT-NOTFOUND) +if(EXISTS "${MAYA_ROOT}/plug-ins/xgen") + set(MAYA_XGEN_ROOT "${MAYA_ROOT}/plug-ins/xgen") +endif() + +set(MAYA_XGEN_INCLUDE_PATH MAYA_XGEN_INCLUDE_PATH-NOTFOUND) + +find_path(MAYA_XGEN_INCLUDE_PATH "XGen/XgWinExport.h" + PATHS + ${MAYA_ROOT} + PATH_SUFFIXES + "${XGEN_PLUGIN}/${MAYA_INC_SUFFIX}" + NO_DEFAULT_PATH + DOC "Maya XGen Include Dir") + +if(MAYA_VERSION GREATER_EQUAL 2020) + find_path(MAYA_XGEN_INCLUDE_PATH "xgen/src/xgcore/XgConfig.h" + PATHS + ${MAYA_ROOT} + PATH_SUFFIXES + "${XGEN_PLUGIN}/${MAYA_INC_SUFFIX}" + NO_DEFAULT_PATH + DOC "Maya XGen Include Dir") +endif() + +set(MAYA_ADSKXGEN_LIBRARY MAYA_ADSKXGEN_LIBRARY-NOTFOUND) +find_library(MAYA_ADSKXGEN_LIBRARY + AdskXGen + libAdskXGen + PATHS + "${MAYA_ROOT}/plug-ins/xgen/lib" + DOC "libAdskXGen Libray Path") + +set(MAYA_XGEN_LIBRARY_PATH MAYA_XGEN_LIBRARY_PATH-NOTFOUND) +if(MAYA_ADSKXGEN_LIBRARY) + set(MAYA_XGEN_LIBRARY_PATH "${MAYA_ROOT}/plug-ins/xgen/lib") +endif() + +set(MAYA_ADSKXPD_LIBRARY MAYA_ADSKXPD_LIBRARY-NOTFOUND) +find_library(MAYA_ADSKXPD_LIBRARY + AdskXpd + libAdskXpd + PATHS + "${MAYA_ROOT}/plug-ins/xgen/lib" + DOC "libAdskXpd Libray Path") + +set(MAYA_ADSKSEEXPR_LIBRARY MAYA_ADSKSEEXPR_LIBRARY-NOTFOUND) +find_library(MAYA_ADSKSEEXPR_LIBRARY + AdskSeExpr + libAdskSeExpr + PATHS + "${MAYA_ROOT}/plug-ins/xgen/lib" + DOC "libAdskSeExpr Libray Path") + + +set(MAYA_LIBRARIES + ${MAYA_FOUNDATION_LIBRARY} + ${MAYA_OPENMAYA_LIBRARY} + ${MAYA_OPENMAYAANIM_LIBRARY} + ${MAYA_OPENMAYAFX_LIBRARY} + ${MAYA_OPENMAYARENDER_LIBRARY} + ${MAYA_OPENMAYAUI_LIBRARY}) + +set(MAYA_XGEN_LIBRARIES + ${MAYA_ADSKXGEN_LIBRARY} + ${MAYA_ADSKXPD_LIBRARY} + ${MAYA_ADSKSEEXPR_LIBRARY}) + +message(STATUS "MAYA_ROOT : ${MAYA_ROOT}") +message(STATUS "MAYA_EXE : ${MAYA_EXE}") +message(STATUS "MAYA_PY_EXE : ${MAYA_PY_EXE}") +message(STATUS "MAYA_INCLUDE_PATH : ${MAYA_INCLUDE_PATH}") +message(STATUS "MAYA_LIBRARY_PATH : ${MAYA_LIBRARY_PATH}") +message(STATUS "MAYA_FOUNDATION_LIBRARY : ${MAYA_FOUNDATION_LIBRARY}") +message(STATUS "MAYA_OPENMAYA_LIBRARY : ${MAYA_OPENMAYA_LIBRARY}") +message(STATUS "MAYA_OPENMAYAANIM_LIBRARY : ${MAYA_OPENMAYAANIM_LIBRARY}") +message(STATUS "MAYA_OPENMAYAFX_LIBRARY : ${MAYA_OPENMAYAFX_LIBRARY}") +message(STATUS "MAYA_OPENMAYARENDER_LIBRARY : ${MAYA_OPENMAYARENDER_LIBRARY}") +message(STATUS "MAYA_OPENMAYAUI_LIBRARY : ${MAYA_OPENMAYAUI_LIBRARY}") +message(STATUS "----------------------------------------------") +message(STATUS "Maya XGen SDK") +message(STATUS "----------------------------------------------") +message(STATUS "MAYA_XGEN_ROOT : ${MAYA_XGEN_ROOT}") +message(STATUS "MAYA_XGEN_INCLUDE_PATH : ${MAYA_XGEN_INCLUDE_PATH}") +message(STATUS "MAYA_XGEN_LIBRARY_PATH : ${MAYA_XGEN_LIBRARY_PATH}") +message(STATUS "MAYA_ADSKXGEN_LIBRARY : ${MAYA_ADSKXGEN_LIBRARY}") +message(STATUS "MAYA_ADSKXPD_LIBRARY : ${MAYA_ADSKXPD_LIBRARY}") +message(STATUS "MAYA_ADSKSEEXPR_LIBRARY : ${MAYA_ADSKSEEXPR_LIBRARY}") + +find_package_handle_standard_args(Maya + REQUIRED_VARS + MAYA_ROOT + MAYA_INCLUDE_PATH + MAYA_LIBRARY_PATH + MAYA_FOUNDATION_LIBRARY + MAYA_OPENMAYA_LIBRARY + MAYA_OPENMAYAANIM_LIBRARY + MAYA_OPENMAYAFX_LIBRARY + MAYA_OPENMAYARENDER_LIBRARY + MAYA_OPENMAYAUI_LIBRARY + VERSION_VAR + MAYA_VERSION + ) diff --git a/cmake/modules/FindMtoa.cmake b/cmake/modules/FindMtoa.cmake new file mode 100644 index 0000000..20a6d2f --- /dev/null +++ b/cmake/modules/FindMtoa.cmake @@ -0,0 +1,143 @@ +include(FindPackageHandleStandardArgs) + +if(NOT DEFINED MTOA_MAYA_VERSION) + set(MTOA_MAYA_VERSION 2018) + if(DEFINED MAYA_VERSION) + set(MTOA_MAYA_VERSION ${MAYA_VERSION}) + endif() + if(DEFINED ENV{MAYA_VERSION}) + set(MTOA_MAYA_VERSION $ENV{MAYA_VERSION}) + endif() +endif() + +set(MTOA_INC_SUFFIX "include") +set(MTOA_LIB_SUFFIX "lib") +set(MTOA_PLUGIN_EXTENSION ".so") +set(MTOA_API_NAME mtoa_api) +set(MTOA_KICK_NAME kick) + +if(WIN32) + set(MTOA_LOCATION "C:/solidangle/mtoadeploy/${MTOA_MAYA_VERSION}") + if(${MTOA_MAYA_VERSION} GREATER 2019) + set(MTOA_LOCATION "C:/Program Files/Autodesk/Arnold/maya${MTOA_MAYA_VERSION}") + endif() + set(MTOA_KICK_NAME "kick.exe") + set(MTOA_PLUGIN_EXTENSION ".dll") +elseif(APPLE) + if(${MTOA_MAYA_VERSION} GREATER 2019) + set(MTOA_LOCATION "/Applications/Autodesk/Arnold/maya${MTOA_MAYA_VERSION}") + endif() +else() + set(MTOA_LOCATION "/opt/solidangle/mtoa/${MTOA_MAYA_VERSION}") + if(${MTOA_MAYA_VERSION} GREATER 2019) + set(MTOA_LOCATION "/usr/autodesk/arnold/maya${MTOA_MAYA_VERSION}") + endif() + set(MTOA_LIB_SUFFIX "bin") +endif() + +if(DEFINED ENV{MTOA_LOCATION}) + set(MTOA_LOCATION $ENV{MTOA_LOCATION}) +endif() + +message(STATUS "MAYA_VERSION : $ENV{MAYA_VERSION}") +message(STATUS "MTOA_MAYA_VERSION : ${MTOA_MAYA_VERSION}") +message(STATUS "MTOA_LOCATION : ${MTOA_LOCATION}") + +set(MTOA_ROOT ${MTOA_LOCATION}) + +if(DEFINED ENV{MTOA_LOCATION}) + set(MTOA_ROOT $ENV{MTOA_LOCATION}) +endif() + +set(MTOA_INCLUDE_PATH MTOA_INCLUDE_PATH-NOTFOUND) + +find_path(MTOA_INCLUDE_PATH extension/Extension.h + PATHS + ${MTOA_LOCATION} + PATH_SUFFIXES + "${MTOA_INC_SUFFIX}/mtoa" + NO_DEFAULT_PATH + DOC "Mtoa Include Dir") + +set(MTOA_VERSION_HEADER "${MTOA_INCLUDE_PATH}/utils/Version.h") + +if(EXISTS ${MTOA_VERSION_HEADER}) + file(STRINGS ${MTOA_VERSION_HEADER} SRC_CONTENT) + foreach(SRC_LINE ${SRC_CONTENT}) + if(${SRC_LINE} MATCHES "^#define MTOA_ARCH_VERSION_NUM") + set(MTOA_VERSION_TYPE MTOA_ARCH_VERSION) + elseif(${SRC_LINE} MATCHES "^#define MTOA_MAJOR_VERSION_NUM") + set(MTOA_VERSION_TYPE MTOA_MAJOR_VERSION_NUM) + elseif(${SRC_LINE} MATCHES "^#define MTOA_MINOR_VERSION_NUM") + set(MTOA_VERSION_TYPE MTOA_MINOR_VERSION_NUM) + elseif(${SRC_LINE} MATCHES "^#define MTOA_FIX_VERSION") + set(MTOA_VERSION_TYPE MTOA_FIX_VERSION) + else() + + endif() + # message(${SRC_LINE}) + string(STRIP "${SRC_LINE}" LINE_BUFFER) + string(REPLACE " " ";" LINE_BUFFER_LIST ${LINE_BUFFER}) + list(LENGTH LINE_BUFFER_LIST _LINE_LENGTH) + list(GET LINE_BUFFER_LIST -1 "${MTOA_VERSION_TYPE}") + # message("## ${LINE_BUFFER_LIST} - ${MTOA_VERSION_TYPE} : ${_LINE_LENGTH}") + endforeach() + + if(DEFINED MTOA_FIX_VERSION) + string(SUBSTRING "${MTOA_FIX_VERSION}" 1 1 MTOA_FIX_VERSION) + set(MTOA_VERSION "${MTOA_ARCH_VERSION}.${MTOA_MAJOR_VERSION_NUM}.${MTOA_MINOR_VERSION_NUM}.${MTOA_FIX_VERSION}") + else() + set(MTOA_VERSION "${MTOA_ARCH_VERSION}.${MTOA_MAJOR_VERSION_NUM}.${MTOA_MINOR_VERSION_NUM}") + endif() +else() + message(FATAL_ERROR "Could not find version header : ${MTOA_VERSION_HEADER}") +endif() + +if(NOT DEFINED MTOA_VERSION) + message(FATAL_ERROR "Could not find MTOA_VERSION") +endif() + +set(MTOA_API_LIBRARY MTOA_API_LIBRARY-NOTFOUND) + +find_library(MTOA_API_LIBRARY ${MTOA_API_NAME} + PATHS + "${MTOA_LOCATION}/${MTOA_LIB_SUFFIX}" + DOC "mtoa_api Libray Path") + +if(MTOA_API_LIBRARY) + set(MTOA_LIBRARY_PATH "${MTOA_LOCATION}/${MTOA_LIB_SUFFIX}") +endif() + +find_program(MTOA_KICK + ${MTOA_KICK_NAME} + PATHS + "${MTOA_LOCATION}/bin" + NO_DEFAULT_PATH + DOC "mtoa kick Path") + +if(EXISTS ${MTOA_KICK}) + execute_process(COMMAND "${MTOA_KICK}" "-av" + WORKING_DIRECTORY "${MTOA_LOCATION}/bin" + RESULT_VARIABLE MTOA_KICK_RESULT + OUTPUT_VARIABLE MTOA_ARNOLD_VERSION) + if(${MTOA_KICK_RESULT} GREATER 0) + message(FATAL_ERROR "Fail to get arnold version : ${MTOA_KICK_RESULT}") + endif() +endif() + +message(STATUS "MTOA_ROOT : ${MTOA_ROOT}") +message(STATUS "MTOA_VERSION : ${MTOA_VERSION}") +message(STATUS "MTOA_ARNOLD_VERSION : ${MTOA_ARNOLD_VERSION}") +message(STATUS "MTOA_INCLUDE_PATH : ${MTOA_INCLUDE_PATH}") +message(STATUS "MTOA_LIBRARY_PATH : ${MTOA_LIBRARY_PATH}") +message(STATUS "MTOA_API : ${MTOA_API_LIBRARY}") +message(STATUS "MTOA_KICK : ${MTOA_KICK}") + +find_package_handle_standard_args(Mtoa + REQUIRED_VARS + MTOA_INCLUDE_PATH + MTOA_LIBRARY_PATH + MTOA_API_LIBRARY + VERSION_VAR + MTOA_VERSION + ) diff --git a/cmake/modules/FindPhoenixFD.cmake b/cmake/modules/FindPhoenixFD.cmake new file mode 100644 index 0000000..14a8e8d --- /dev/null +++ b/cmake/modules/FindPhoenixFD.cmake @@ -0,0 +1,135 @@ +include(FindPackageHandleStandardArgs) + +if(DEFINED ENV{PHX_LOCATION}) + set(PHX_LOCATION $ENV{PHX_LOCATION}) +endif() + + +set(PHX_INC_SUFFIX "include") +set(PHX_LIB_SUFFIX "lib") + +find_path(PHX_INCLUDE_PATH phoenix_ver.h + PATHS + ${PHX_LOCATION} + PATH_SUFFIXES + "${PHX_INC_SUFFIX}" + NO_DEFAULT_PATH + DOC "PhoenixFD Include Dir") + +set(PHX_VERSION_HEADER "${MTOA_INCLUDE_PATH}/phoenix_ver.h") + +if(EXISTS ${PHX_VERSION_HEADER}) + file(STRINGS ${PHX_VERSION_HEADER} SRC_CONTENT) + foreach(SRC_LINE ${SRC_CONTENT}) + if(${SRC_LINE} MATCHES "^#define PHOENIX_VERSION") + set(PHX_VERSION_TYPE PHOENIX_VERSION) + elseif(${SRC_LINE} MATCHES "^#define PHOENIX_VERSION_SHORT") + set(PHX_VERSION_TYPE PHOENIX_VERSION_SHORT) + elseif(${SRC_LINE} MATCHES "^#define PHOENIX_VERSION_NUMERIC") + set(PHX_VERSION_TYPE PHOENIX_VERSION_NUMERIC) + else() + continue() + endif() + + string(STRIP "${SRC_LINE}" LINE_BUFFER) + string(REPLACE " " ";" LINE_BUFFER_LIST ${LINE_BUFFER}) + list(LENGTH LINE_BUFFER_LIST _LINE_LENGTH) + list(GET LINE_BUFFER_LIST -1 "${PHX_VERSION_TYPE}") + endforeach() + if(DEFINED PHOENIX_VERSION) + set(PHX_VERSION ${PHOENIX_VERSION}) + endif() +endif() + +if(NOT DEFINED PHX_VERSION) + message(FATAL_ERROR "Could not find PHX_VERSION") +endif() + +set(PHX_AURLOADER_LIBRARY PHX_AULOADER_LIBRARY_LIBRARY-NOTFOUND) +find_library(PHX_AURLOADER_LIBRARY aurloader_s + PATHS + "${PHX_LOCATION}/${PHX_LIB_SUFFIX}" + DOC "aurloader library" +) + +if(PHX_AURLOADER_LIBRARY) + set(PHX_LIBRIRES PHX_AURLOADER_LIBRARY) +endif() + +set(PHX_AURRAMP_LIBRARY PHX_AURRAMP_LIBRARY-NOTFOUND) +find_library(PHX_AURRAMP_LIBRARY aurramp_s + PATHS + "${PHX_LOCATION}/${PHX_LIB_SUFFIX}" + DOC "aurramp library" +) + +if(PHX_AURRAMP_LIBRARY) + list(APPEND PHX_LIBRIRES PHX_AURRAMP_LIBRARY) +endif() + +set(PHX_PHXUTILS_LIBRARY PHX_PHXUTILS_LIBRARY-NOTFOUND) +find_library(PHX_PHXUTILS_LIBRARY phxutils_s + PATHS + "${PHX_LOCATION}/${PHX_LIB_SUFFIX}" + DOC "phxutils library" +) + +if(PHX_PHXUTILS_LIBRARY) + list(APPEND PHX_LIBRIRES PHX_PHXUTILS_LIBRARY) +endif() + +set(PHX_VUTILS_LIBRARY PHX_VUTILS_LIBRARY-NOTFOUND) +find_library(PHX_PHXUTILS_LIBRARY vutils_s + PATHS + "${PHX_LOCATION}/${PHX_LIB_SUFFIX}" + DOC "vutils library" +) + +if(PHX_VUTILS_LIBRARY) + list(APPEND PHX_LIBRIRES PHX_VUTILS_LIBRARY) +endif() + +set(PHX_GUI_UTILS_QT_LIBRARY PHX_GUI_UTILS_QT_LIBRARY-NOTFOUND) +find_library(PHX_GUI_UTILS_QT_LIBRARY gui_utils_qt_s + PATHS + "${PHX_LOCATION}/${PHX_LIB_SUFFIX}" + DOC "gui_utils_qt library" +) + +if(PHX_GUI_UTILS_QT_LIBRARY) + list(APPEND PHX_LIBRIRES PHX_GUI_UTILS_QT_LIBRARY) +endif() + +set(PHX_LIBRARY_PATH PHX_LIBRARY_PATH-NOTFOUND) + +if(PHX_PHXUTILS_LIBRARY) + set(PHX_LIBRARY_PATH "${PHX_LOCATION}/${PHX_LIB_SUFFIX}") +endif() + +#set(PHX_LIBRIRES +# ${PHX_AURLOADER_LIBRARY} +# ${PHX_AURRAMP_LIBRARY} +# ${PHX_PHXUTILS_LIBRARY} +# ${PHX_VUTILS_LIBRARY} +# ${PHX_GUI_UTILS_QT_LIBRARY} +#) + +message(STATUS "PHX_LOCATION : ${PHX_LOCATION}") +message(STATUS "PHX_VERSION : ${PHX_VERSION}") +message(STATUS "PHX_INCLUDE_PATH : ${PHX_INCLUDE_PATH}") +message(STATUS "PHX_LIBRARY_PATH : ${PHX_LIBRARY_PATH}") +message(STATUS "PHX_AURLOADER_LIBRARY : ${PHX_AURLOADER_LIBRARY}") +message(STATUS "PHX_AURRAMP_LIBRARY : ${PHX_AURRAMP_LIBRARY}") +message(STATUS "PHX_PHXUTILS_LIBRARY : ${PHX_PHXUTILS_LIBRARY}") +message(STATUS "PHX_VUTILS_LIBRARY : ${PHX_VUTILS_LIBRARY}") +message(STATUS "PHX_GUI_UTILS_QT_LIBRARY : ${PHX_GUI_UTILS_QT_LIBRARY}") + + +find_package_handle_standard_args(PHX + REQUIRED_VARS + PHX_INCLUDE_PATH + PHX_LIBRARY_PATH + PHX_LIBRIRES + VERSION_VAR + PHX_VERSION + ) \ No newline at end of file diff --git a/cmd/post_build_extension.bat b/cmd/post_build_extension.bat new file mode 100644 index 0000000..1890890 --- /dev/null +++ b/cmd/post_build_extension.bat @@ -0,0 +1,72 @@ +@echo off +setlocal enabledelayedexpansion + +set SOLUTION_NAME=%1 +set PROJECT_NAME=%2 +set TARGET_PATH=%3 +set DEST=%~f4 + +set CURRENT_DIR=%~dp0 +set PROJECT_SRC_DIR=%CURRENT_DIR:~0,-1%\..\src\%PROJECT_NAME% +for %%f in ("%PROJECT_SRC_DIR%") do ( set PROJECT_SRC_DIR=%%~ff ) +echo %PROJECT_SRC_DIR% +echo %TARGET_PATH% +:: Deploy dll +::------------------------------------ +echo ## Deploy dll + +set DEST_DIR=%DEST%\extensions + +if not exist "!DEST_DIR!" ( + mkdir !DEST_DIR! +) + +for %%f in ("%TARGET_PATH%") do ( + set FILENAME=%%~ff +) + +copy !FILENAME! !DEST_DIR! /Y/B > nul + +echo ## Deploy !FILENAME! to !DEST_DIR! + +:: Deploy mtd +::------------------------------------ +echo ## Deploy mtd +for /R %PROJECT_SRC_DIR% %%a in (*.mtd) do ( + + set DEST_DIR=%DEST%\extensions + + if not exist "!DEST_DIR!" ( + mkdir !DEST_DIR! + ) + + copy %%a !DEST_DIR! /Y/B > nul + + for %%f in ("%%a") do ( + set FILENAME=%%~ff + ) + + echo ## Deploy !FILENAME! to !DEST_DIR! +) + +:: Deploy templete +::------------------------------------ +echo ## Deploy template +for /R %PROJECT_SRC_DIR% %%a in (*.py) do ( + + set DEST_DIR=%DEST%\templates + + if not exist "!DEST_DIR!" ( + mkdir !DEST_DIR! + ) + + copy %%a !DEST_DIR! /Y/B > nul + + for %%f in ("%%a") do ( + set FILENAME=%%~ff + ) + + echo ## Deploy !FILENAME! to !DEST_DIR! +) +echo ## Deploy Finish +endlocal \ No newline at end of file diff --git a/cmd/post_build_shader.bat b/cmd/post_build_shader.bat new file mode 100644 index 0000000..5ab2584 --- /dev/null +++ b/cmd/post_build_shader.bat @@ -0,0 +1,72 @@ +@echo off +setlocal enabledelayedexpansion + +set SOLUTION_NAME=%1 +set PROJECT_NAME=%2 +set TARGET_PATH=%3 +set DEST=%~f4 + +set CURRENT_DIR=%~dp0 +set PROJECT_SRC_DIR=%CURRENT_DIR:~0,-1%\..\src\%PROJECT_NAME% +for %%f in ("%PROJECT_SRC_DIR%") do ( set PROJECT_SRC_DIR=%%~ff ) +echo %PROJECT_SRC_DIR% +echo %TARGET_PATH% +:: Deploy dll +::------------------------------------ +echo ## Deploy dll + +set DEST_DIR=%DEST%\shaders + +if not exist "!DEST_DIR!" ( + mkdir !DEST_DIR! +) + +for %%f in ("%TARGET_PATH%") do ( + set FILENAME=%%~ff +) + +copy !FILENAME! !DEST_DIR! /Y/B > nul + +echo ## Deploy !FILENAME! to !DEST_DIR! + +:: Deploy mtd +::------------------------------------ +echo ## Deploy mtd +for /R %PROJECT_SRC_DIR% %%a in (*.mtd) do ( + + set DEST_DIR=%DEST%\shaders + + if not exist "!DEST_DIR!" ( + mkdir !DEST_DIR! + ) + + copy %%a !DEST_DIR! /Y/B > nul + + for %%f in ("%%a") do ( + set FILENAME=%%~ff + ) + + echo ## Deploy !FILENAME! to !DEST_DIR! +) + +:: Deploy templete +::------------------------------------ +echo ## Deploy template +for /R %PROJECT_SRC_DIR% %%a in (*.py) do ( + + set DEST_DIR=%DEST%\templates + + if not exist "!DEST_DIR!" ( + mkdir !DEST_DIR! + ) + + copy %%a !DEST_DIR! /Y/B > nul + + for %%f in ("%%a") do ( + set FILENAME=%%~ff + ) + + echo ## Deploy !FILENAME! to !DEST_DIR! +) +echo ## Deploy Finish +endlocal \ No newline at end of file diff --git a/msvc/Maya.props b/msvc/Maya.props new file mode 100644 index 0000000..c2b0316 --- /dev/null +++ b/msvc/Maya.props @@ -0,0 +1,28 @@ + + + + + 2018 + C:\Program Files\Autodesk\Maya$(MAYA_VER) + + + .dll + + + + $(MAYA_LOCATION)\lib;%(AdditionalLibraryDirectories) + Foundation.lib;OpenMaya.lib;OpenMayaAnim.lib;OpenMayaFX.lib;OpenMayaRender.lib;OpenMayaUI.lib;%(AdditionalDependencies) + + + $(MAYA_LOCATION)\include;%(AdditionalIncludeDirectories) + + + + + $(MAYA_VER) + + + $(MAYA_LOCATION) + + + \ No newline at end of file diff --git a/msvc/Mtoa.props b/msvc/Mtoa.props new file mode 100644 index 0000000..c13dc94 --- /dev/null +++ b/msvc/Mtoa.props @@ -0,0 +1,31 @@ + + + + + C:\solidangle\mtoadeploy + $(MTOA_ROOT)\$(MAYA_VER) + + + + + $(MTOA_LOCATION)\include;%(AdditionalIncludeDirectories) + + + $(MTOA_LOCATION)\lib;%(AdditionalLibraryDirectories) + mtoa_api.lib;%(AdditionalDependencies) + + + copy $(TargetPath) $(solutionDir)..\build\$(solutionName)\extensions /Y/B +$(SolutionDir)..\cmd\post_build_extension.bat $(SolutionName) $(ProjectName) $(TargetPath) $(solutionDir)..\build\$(solutionName) + + + + + $(MTOA_ROOT) + true + + + $(MTOA_LOCATION) + + + \ No newline at end of file diff --git a/msvc/apBoolean/apBoolean.vcxproj b/msvc/apBoolean/apBoolean.vcxproj new file mode 100644 index 0000000..5e79b7d --- /dev/null +++ b/msvc/apBoolean/apBoolean.vcxproj @@ -0,0 +1,128 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {7CB4B958-2FA5-4B56-A435-FF15C61B7CD9} + apBoolean + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + DynamicLibrary + true + v140 + MultiByte + + + DynamicLibrary + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + Disabled + true + true + true + + + true + true + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/apBoolean/apBoolean.vcxproj.filters b/msvc/apBoolean/apBoolean.vcxproj.filters new file mode 100644 index 0000000..4e16888 --- /dev/null +++ b/msvc/apBoolean/apBoolean.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/msvc/apBoolean/apBoolean.vcxproj.user b/msvc/apBoolean/apBoolean.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/msvc/apBoolean/apBoolean.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/msvc/apChaosMosaic/apChaosMosaic.vcxproj b/msvc/apChaosMosaic/apChaosMosaic.vcxproj new file mode 100644 index 0000000..cc75d08 --- /dev/null +++ b/msvc/apChaosMosaic/apChaosMosaic.vcxproj @@ -0,0 +1,125 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {F5008C52-3846-4E97-A2E2-469151020F32} + apChaosMosaic + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + DynamicLibrary + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/apChaosMosaic/apChaosMosaic.vcxproj.filters b/msvc/apChaosMosaic/apChaosMosaic.vcxproj.filters new file mode 100644 index 0000000..546603e --- /dev/null +++ b/msvc/apChaosMosaic/apChaosMosaic.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/msvc/apChaosMosaic/apChaosMosaic.vcxproj.user b/msvc/apChaosMosaic/apChaosMosaic.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/msvc/apChaosMosaic/apChaosMosaic.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/msvc/apClosure/apClosure.vcxproj b/msvc/apClosure/apClosure.vcxproj new file mode 100644 index 0000000..eca7f1c --- /dev/null +++ b/msvc/apClosure/apClosure.vcxproj @@ -0,0 +1,130 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {DB51624F-B4D2-454B-B82D-01C1A1DA44A8} + apClosure + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + DynamicLibrary + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/apClosure/apClosure.vcxproj.filters b/msvc/apClosure/apClosure.vcxproj.filters new file mode 100644 index 0000000..90ce886 --- /dev/null +++ b/msvc/apClosure/apClosure.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Resource Files + + + Resource Files + + + + + Source Files + + + \ No newline at end of file diff --git a/msvc/apClosure/apClosure.vcxproj.user b/msvc/apClosure/apClosure.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/msvc/apClosure/apClosure.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/msvc/apCurveStandIn/CurveStandIn.cpp b/msvc/apCurveStandIn/CurveStandIn.cpp new file mode 100644 index 0000000..c70ee68 --- /dev/null +++ b/msvc/apCurveStandIn/CurveStandIn.cpp @@ -0,0 +1,40 @@ +#include "CurveStandIn.h" + +#include +#include +#include + +MTypeId CurveStandIn::id(0x88015); +MObject CurveStandIn::aFileName; +MObject CurveStandIn::aOutputCurve; + +CurveStandIn::CurveStandIn() +{ +} + +CurveStandIn::~CurveStandIn() +{ +} + +MStatus CurveStandIn::compute(const MPlug& plug, MDataBlock& dataBlock) +{ + return MS::kSuccess; +} + +void* CurveStandIn::creator() +{ + return new CurveStandIn(); +} + +MStatus CurveStandIn::initialize() +{ + MStatus status; + MFnTypedAttribute tAttr; + aFileName = tAttr.create("fileName", "fn", MFnData::kString, &status); + tAttr.setUsedAsFilename(true); + addAttribute(aFileName); + + aOutputCurve = tAttr.create("outputCurve", "oc", MFnData::kNurbsCurve, &status); + addAttribute(aOutputCurve); + return status; +} diff --git a/msvc/apCurveStandIn/CurveStandIn.h b/msvc/apCurveStandIn/CurveStandIn.h new file mode 100644 index 0000000..eb57d97 --- /dev/null +++ b/msvc/apCurveStandIn/CurveStandIn.h @@ -0,0 +1,17 @@ +#include + +class CurveStandIn : public MPxSurfaceShape +{ +public: + CurveStandIn(); + virtual ~CurveStandIn(); + + virtual MStatus compute(const MPlug& plug, MDataBlock& dataBlock); + static void* creator(); + static MStatus initialize(); + +public: + static MTypeId id; + static MObject aFileName; + static MObject aOutputCurve; +}; \ No newline at end of file diff --git a/msvc/apCurveStandIn/CurveStandInTranslator.cpp b/msvc/apCurveStandIn/CurveStandInTranslator.cpp new file mode 100644 index 0000000..e69de29 diff --git a/msvc/apCurveStandIn/CurveStandInTranslator.h b/msvc/apCurveStandIn/CurveStandInTranslator.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/msvc/apCurveStandIn/CurveStandInTranslator.h @@ -0,0 +1 @@ +#pragma once diff --git a/msvc/apCurveStandIn/CurveStandInUI.cpp b/msvc/apCurveStandIn/CurveStandInUI.cpp new file mode 100644 index 0000000..38de746 --- /dev/null +++ b/msvc/apCurveStandIn/CurveStandInUI.cpp @@ -0,0 +1,27 @@ +#include "CurveStandInUI.h" + +CurveStandInUI::CurveStandInUI() +{ +} + +CurveStandInUI::~CurveStandInUI() +{ +} + +void CurveStandInUI::getDrawRequests(const MDrawInfo& info, bool objectAndActiveOnly, MDrawRequestQueue& requests) +{ +} + +void CurveStandInUI::draw(const MDrawRequest& requests, M3dView& view) const +{ +} + +bool CurveStandInUI::select(MSelectInfo& selectInfo, MSelectionList& selectionList, MPointArray& worldSpaceSelectPts) const +{ + return false; +} + +void* CurveStandInUI::creator() +{ + return new CurveStandInUI(); +} diff --git a/msvc/apCurveStandIn/CurveStandInUI.h b/msvc/apCurveStandIn/CurveStandInUI.h new file mode 100644 index 0000000..b4a8682 --- /dev/null +++ b/msvc/apCurveStandIn/CurveStandInUI.h @@ -0,0 +1,23 @@ +#pragma once +#include + +class CurveStandInUI : public MPxSurfaceShapeUI +{ +public: + CurveStandInUI(); + ~CurveStandInUI() override; + + void getDrawRequests(const MDrawInfo& info, + bool objectAndActiveOnly, + MDrawRequestQueue& requests) override; + void draw( const MDrawRequest& requests, + M3dView& view) const override; + + // Main selection routine + // + bool select( MSelectInfo& selectInfo, + MSelectionList& selectionList, + MPointArray& worldSpaceSelectPts ) const override; + + static void* creator(); +}; \ No newline at end of file diff --git a/msvc/apCurveStandIn/Plugin.cpp b/msvc/apCurveStandIn/Plugin.cpp new file mode 100644 index 0000000..bb33def --- /dev/null +++ b/msvc/apCurveStandIn/Plugin.cpp @@ -0,0 +1,22 @@ +#include "CurveStandIn.h" + +#include + +extern "C" +{ + DLLEXPORT void initializeExtension(CExtension& plugin) + { + plugin.Requires("AbcImport"); + plugin.RegisterNode("CurveStandIn", + CurveStandIn::id, + CurveStandIn::creator, + CurveStandIn::initialize, + MPxNode::kSurfaceShape); + + //extension.RegisterTranslator("CurveStandIn", "CurveStandInTranslator"); + } + + DLLEXPORT void deinitializeExtension(CExtension &plugin) + { + } +} \ No newline at end of file diff --git a/msvc/apCurveStandIn/apCurveStandIn.vcxproj b/msvc/apCurveStandIn/apCurveStandIn.vcxproj new file mode 100644 index 0000000..d3cbbf2 --- /dev/null +++ b/msvc/apCurveStandIn/apCurveStandIn.vcxproj @@ -0,0 +1,170 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + 16.0 + Win32Proj + {c0a60136-a1c2-456a-9d52-1ac63ae70566} + apCurveStandIn + 8.1 + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;APCURVESTANDIN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + + + + + Level3 + true + true + true + WIN32;NDEBUG;APCURVESTANDIN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + true + true + false + + + + + Level3 + true + _DEBUG;APCURVESTANDIN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + + + + + Level3 + true + true + true + NDEBUG;APCURVESTANDIN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + + + Windows + true + true + true + false + + + + + + \ No newline at end of file diff --git a/msvc/apCurveStandIn/apCurveStandIn.vcxproj.filters b/msvc/apCurveStandIn/apCurveStandIn.vcxproj.filters new file mode 100644 index 0000000..8f11add --- /dev/null +++ b/msvc/apCurveStandIn/apCurveStandIn.vcxproj.filters @@ -0,0 +1,36 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/msvc/apCurveStandIn/apCurveStandIn.vcxproj.user b/msvc/apCurveStandIn/apCurveStandIn.vcxproj.user new file mode 100644 index 0000000..5df420f --- /dev/null +++ b/msvc/apCurveStandIn/apCurveStandIn.vcxproj.user @@ -0,0 +1,6 @@ + + + + false + + \ No newline at end of file diff --git a/msvc/apEntrySwitch/apEntrySwitch.vcxproj b/msvc/apEntrySwitch/apEntrySwitch.vcxproj new file mode 100644 index 0000000..6b4d133 --- /dev/null +++ b/msvc/apEntrySwitch/apEntrySwitch.vcxproj @@ -0,0 +1,125 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {7884B635-79EE-4F4F-A2E6-351DC4FFE5D1} + apEntrySwitch + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + DynamicLibrary + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + Disabled + true + true + true + + + true + true + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/apEntrySwitch/apEntrySwitch.vcxproj.filters b/msvc/apEntrySwitch/apEntrySwitch.vcxproj.filters new file mode 100644 index 0000000..4cc319a --- /dev/null +++ b/msvc/apEntrySwitch/apEntrySwitch.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/msvc/apEntrySwitch/apEntrySwitch.vcxproj.user b/msvc/apEntrySwitch/apEntrySwitch.vcxproj.user new file mode 100644 index 0000000..12a5054 --- /dev/null +++ b/msvc/apEntrySwitch/apEntrySwitch.vcxproj.user @@ -0,0 +1,6 @@ + + + + false + + \ No newline at end of file diff --git a/msvc/apGrayBall/apGrayBall.vcxproj b/msvc/apGrayBall/apGrayBall.vcxproj new file mode 100644 index 0000000..353e2fb --- /dev/null +++ b/msvc/apGrayBall/apGrayBall.vcxproj @@ -0,0 +1,129 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {A750850B-D551-4A7A-BD85-A43EAC09B457} + apGrayBall + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + DynamicLibrary + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/apGrayBall/apGrayBall.vcxproj.filters b/msvc/apGrayBall/apGrayBall.vcxproj.filters new file mode 100644 index 0000000..5923e3c --- /dev/null +++ b/msvc/apGrayBall/apGrayBall.vcxproj.filters @@ -0,0 +1,35 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Resource Files + + + Resource Files + + + + + Header Files + + + \ No newline at end of file diff --git a/msvc/apGrayBall/apGrayBall.vcxproj.user b/msvc/apGrayBall/apGrayBall.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/msvc/apGrayBall/apGrayBall.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/msvc/apHairBSDF/apHairBSDF.vcxproj b/msvc/apHairBSDF/apHairBSDF.vcxproj new file mode 100644 index 0000000..d80ce36 --- /dev/null +++ b/msvc/apHairBSDF/apHairBSDF.vcxproj @@ -0,0 +1,130 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {56B453EF-BD2A-4165-A834-17EB2C3FA0B1} + apHairBSDF + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + DynamicLibrary + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/apHairBSDF/apHairBSDF.vcxproj.filters b/msvc/apHairBSDF/apHairBSDF.vcxproj.filters new file mode 100644 index 0000000..27a1ccf --- /dev/null +++ b/msvc/apHairBSDF/apHairBSDF.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/msvc/apHairBSDF/apHairBSDF.vcxproj.user b/msvc/apHairBSDF/apHairBSDF.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/msvc/apHairBSDF/apHairBSDF.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/msvc/apInteriorMapping/apInteriorMapping.vcxproj b/msvc/apInteriorMapping/apInteriorMapping.vcxproj new file mode 100644 index 0000000..a187b4f --- /dev/null +++ b/msvc/apInteriorMapping/apInteriorMapping.vcxproj @@ -0,0 +1,130 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {AF82561F-B596-4032-9674-A3D22BFCE7F0} + apInteriorMapping + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + DynamicLibrary + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/apInteriorMapping/apInteriorMapping.vcxproj.filters b/msvc/apInteriorMapping/apInteriorMapping.vcxproj.filters new file mode 100644 index 0000000..9a5ab55 --- /dev/null +++ b/msvc/apInteriorMapping/apInteriorMapping.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/msvc/apInteriorMapping/apInteriorMapping.vcxproj.user b/msvc/apInteriorMapping/apInteriorMapping.vcxproj.user new file mode 100644 index 0000000..12a5054 --- /dev/null +++ b/msvc/apInteriorMapping/apInteriorMapping.vcxproj.user @@ -0,0 +1,6 @@ + + + + false + + \ No newline at end of file diff --git a/msvc/apIrradianceCache/apIrradianceCache.vcxproj b/msvc/apIrradianceCache/apIrradianceCache.vcxproj new file mode 100644 index 0000000..85313ab --- /dev/null +++ b/msvc/apIrradianceCache/apIrradianceCache.vcxproj @@ -0,0 +1,126 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {F7878B46-CB83-44D9-B1B2-D90590B4A956} + apIrradianceCache + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + + \ No newline at end of file diff --git a/msvc/apIrradianceCache/apIrradianceCache.vcxproj.filters b/msvc/apIrradianceCache/apIrradianceCache.vcxproj.filters new file mode 100644 index 0000000..6a1782f --- /dev/null +++ b/msvc/apIrradianceCache/apIrradianceCache.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + \ No newline at end of file diff --git a/msvc/apIrradianceCache/apIrradianceCache.vcxproj.user b/msvc/apIrradianceCache/apIrradianceCache.vcxproj.user new file mode 100644 index 0000000..966b4ff --- /dev/null +++ b/msvc/apIrradianceCache/apIrradianceCache.vcxproj.user @@ -0,0 +1,6 @@ + + + + true + + \ No newline at end of file diff --git a/msvc/apMetalBSDF/apMetalBSDF.vcxproj b/msvc/apMetalBSDF/apMetalBSDF.vcxproj new file mode 100644 index 0000000..661d412 --- /dev/null +++ b/msvc/apMetalBSDF/apMetalBSDF.vcxproj @@ -0,0 +1,130 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {2ACA60C6-E8F1-4B5D-9088-5A95F6813C0F} + apMetalBSDF + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + DynamicLibrary + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/apMetalBSDF/apMetalBSDF.vcxproj.filters b/msvc/apMetalBSDF/apMetalBSDF.vcxproj.filters new file mode 100644 index 0000000..c358ee2 --- /dev/null +++ b/msvc/apMetalBSDF/apMetalBSDF.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/msvc/apMetalBSDF/apMetalBSDF.vcxproj.user b/msvc/apMetalBSDF/apMetalBSDF.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/msvc/apMetalBSDF/apMetalBSDF.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/msvc/apMicrofacetBSDF/apMicrofacetBSDF.vcxproj b/msvc/apMicrofacetBSDF/apMicrofacetBSDF.vcxproj new file mode 100644 index 0000000..0c33fc3 --- /dev/null +++ b/msvc/apMicrofacetBSDF/apMicrofacetBSDF.vcxproj @@ -0,0 +1,130 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {D065D515-FA81-46F1-9BF5-2BD8830B379A} + apMicrofacetBSDF + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + DynamicLibrary + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/apMicrofacetBSDF/apMicrofacetBSDF.vcxproj.filters b/msvc/apMicrofacetBSDF/apMicrofacetBSDF.vcxproj.filters new file mode 100644 index 0000000..0dd347c --- /dev/null +++ b/msvc/apMicrofacetBSDF/apMicrofacetBSDF.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/msvc/apMicrofacetBSDF/apMicrofacetBSDF.vcxproj.user b/msvc/apMicrofacetBSDF/apMicrofacetBSDF.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/msvc/apMicrofacetBSDF/apMicrofacetBSDF.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/msvc/apMicrofacetRefractionBSDF/apMicrofacetRefractionBSDF.vcxproj b/msvc/apMicrofacetRefractionBSDF/apMicrofacetRefractionBSDF.vcxproj new file mode 100644 index 0000000..fb29785 --- /dev/null +++ b/msvc/apMicrofacetRefractionBSDF/apMicrofacetRefractionBSDF.vcxproj @@ -0,0 +1,130 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {2BE54595-4B99-4E0C-B743-FBC00E7D8082} + apMicrofacetRefractionBSDF + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + DynamicLibrary + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/apMicrofacetRefractionBSDF/apMicrofacetRefractionBSDF.vcxproj.filters b/msvc/apMicrofacetRefractionBSDF/apMicrofacetRefractionBSDF.vcxproj.filters new file mode 100644 index 0000000..cd8561f --- /dev/null +++ b/msvc/apMicrofacetRefractionBSDF/apMicrofacetRefractionBSDF.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/msvc/apMicrofacetRefractionBSDF/apMicrofacetRefractionBSDF.vcxproj.user b/msvc/apMicrofacetRefractionBSDF/apMicrofacetRefractionBSDF.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/msvc/apMicrofacetRefractionBSDF/apMicrofacetRefractionBSDF.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/msvc/apMotionVector/apMotionVector.vcxproj b/msvc/apMotionVector/apMotionVector.vcxproj new file mode 100644 index 0000000..1bbef3d --- /dev/null +++ b/msvc/apMotionVector/apMotionVector.vcxproj @@ -0,0 +1,130 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {F39996B4-EC69-4E59-BF5C-2CEA4E0E679A} + apMotionVector + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/apMotionVector/apMotionVector.vcxproj.filters b/msvc/apMotionVector/apMotionVector.vcxproj.filters new file mode 100644 index 0000000..6a1782f --- /dev/null +++ b/msvc/apMotionVector/apMotionVector.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + \ No newline at end of file diff --git a/msvc/apMotionVector/apMotionVector.vcxproj.user b/msvc/apMotionVector/apMotionVector.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/msvc/apMotionVector/apMotionVector.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/msvc/apOrenNayerBSDF/apOrenNayerBSDF.vcxproj b/msvc/apOrenNayerBSDF/apOrenNayerBSDF.vcxproj new file mode 100644 index 0000000..a81189b --- /dev/null +++ b/msvc/apOrenNayerBSDF/apOrenNayerBSDF.vcxproj @@ -0,0 +1,130 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {A0279F67-6D8F-404F-9D13-76538301E683} + apOrenNayerBSDF + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + DynamicLibrary + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/apOrenNayerBSDF/apOrenNayerBSDF.vcxproj.filters b/msvc/apOrenNayerBSDF/apOrenNayerBSDF.vcxproj.filters new file mode 100644 index 0000000..62c1d91 --- /dev/null +++ b/msvc/apOrenNayerBSDF/apOrenNayerBSDF.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/msvc/apOrenNayerBSDF/apOrenNayerBSDF.vcxproj.user b/msvc/apOrenNayerBSDF/apOrenNayerBSDF.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/msvc/apOrenNayerBSDF/apOrenNayerBSDF.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/msvc/apParallaxMap/apParallaxMap.vcxproj b/msvc/apParallaxMap/apParallaxMap.vcxproj new file mode 100644 index 0000000..5ffca55 --- /dev/null +++ b/msvc/apParallaxMap/apParallaxMap.vcxproj @@ -0,0 +1,130 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {5A75B594-5757-46A0-A498-7988EFFD2FDD} + apParallaxMap + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + DynamicLibrary + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + Disabled + true + true + true + + + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/apParallaxMap/apParallaxMap.vcxproj.filters b/msvc/apParallaxMap/apParallaxMap.vcxproj.filters new file mode 100644 index 0000000..b1d37c0 --- /dev/null +++ b/msvc/apParallaxMap/apParallaxMap.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/msvc/apParallaxMap/apParallaxMap.vcxproj.user b/msvc/apParallaxMap/apParallaxMap.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/msvc/apParallaxMap/apParallaxMap.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/msvc/apShaders.sln b/msvc/apShaders.sln new file mode 100644 index 0000000..3f24c22 --- /dev/null +++ b/msvc/apShaders.sln @@ -0,0 +1,211 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "apBoolean", "apBoolean\apBoolean.vcxproj", "{7CB4B958-2FA5-4B56-A435-FF15C61B7CD9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "apEntrySwitch", "apEntrySwitch\apEntrySwitch.vcxproj", "{7884B635-79EE-4F4F-A2E6-351DC4FFE5D1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "apUvRange", "apUvRange\apUvRange.vcxproj", "{7DB572DF-1CA8-43EA-AF0B-286ABBF0EAEA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "apChaosMosaic", "apChaosMosaic\apChaosMosaic.vcxproj", "{F5008C52-3846-4E97-A2E2-469151020F32}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "apGrayBall", "apGrayBall\apGrayBall.vcxproj", "{A750850B-D551-4A7A-BD85-A43EAC09B457}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "apParallaxMap", "apParallaxMap\apParallaxMap.vcxproj", "{5A75B594-5757-46A0-A498-7988EFFD2FDD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "apClosure", "apClosure\apClosure.vcxproj", "{DB51624F-B4D2-454B-B82D-01C1A1DA44A8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "apOrenNayerBSDF", "apOrenNayerBSDF\apOrenNayerBSDF.vcxproj", "{A0279F67-6D8F-404F-9D13-76538301E683}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "apMicrofacetBSDF", "apMicrofacetBSDF\apMicrofacetBSDF.vcxproj", "{D065D515-FA81-46F1-9BF5-2BD8830B379A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "apMicrofacetRefractionBSDF", "apMicrofacetRefractionBSDF\apMicrofacetRefractionBSDF.vcxproj", "{2BE54595-4B99-4E0C-B743-FBC00E7D8082}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "apMetalBSDF", "apMetalBSDF\apMetalBSDF.vcxproj", "{2ACA60C6-E8F1-4B5D-9088-5A95F6813C0F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "apHairBSDF", "apHairBSDF\apHairBSDF.vcxproj", "{56B453EF-BD2A-4165-A834-17EB2C3FA0B1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "apZinkeBSDF", "apZinkeBSDF\apZinkeBSDF.vcxproj", "{9633BE9A-131A-453E-9AB9-CE77AEE9F72C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "apInteriorMapping", "apInteriorMapping\apInteriorMapping.vcxproj", "{AF82561F-B596-4032-9674-A3D22BFCE7F0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "apSurfaceSample", "apSurfaceSample\apSurfaceSample.vcxproj", "{65D4408B-2D18-48B4-8132-63A0420E86DD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "apMotionVector", "apMotionVector\apMotionVector.vcxproj", "{F39996B4-EC69-4E59-BF5C-2CEA4E0E679A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "apIrradianceCache", "apIrradianceCache\apIrradianceCache.vcxproj", "{F7878B46-CB83-44D9-B1B2-D90590B4A956}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "apCurveStandIn", "apCurveStandIn\apCurveStandIn.vcxproj", "{C0A60136-A1C2-456A-9D52-1AC63AE70566}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "apVolume", "apVolume\apVolume.vcxproj", "{3AF88D29-3590-4579-9ED6-FFF8F2311456}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7CB4B958-2FA5-4B56-A435-FF15C61B7CD9}.Debug|x64.ActiveCfg = Debug|x64 + {7CB4B958-2FA5-4B56-A435-FF15C61B7CD9}.Debug|x64.Build.0 = Debug|x64 + {7CB4B958-2FA5-4B56-A435-FF15C61B7CD9}.Debug|x86.ActiveCfg = Debug|Win32 + {7CB4B958-2FA5-4B56-A435-FF15C61B7CD9}.Debug|x86.Build.0 = Debug|Win32 + {7CB4B958-2FA5-4B56-A435-FF15C61B7CD9}.Release|x64.ActiveCfg = Release|x64 + {7CB4B958-2FA5-4B56-A435-FF15C61B7CD9}.Release|x64.Build.0 = Release|x64 + {7CB4B958-2FA5-4B56-A435-FF15C61B7CD9}.Release|x86.ActiveCfg = Release|Win32 + {7CB4B958-2FA5-4B56-A435-FF15C61B7CD9}.Release|x86.Build.0 = Release|Win32 + {7884B635-79EE-4F4F-A2E6-351DC4FFE5D1}.Debug|x64.ActiveCfg = Debug|x64 + {7884B635-79EE-4F4F-A2E6-351DC4FFE5D1}.Debug|x64.Build.0 = Debug|x64 + {7884B635-79EE-4F4F-A2E6-351DC4FFE5D1}.Debug|x86.ActiveCfg = Debug|Win32 + {7884B635-79EE-4F4F-A2E6-351DC4FFE5D1}.Debug|x86.Build.0 = Debug|Win32 + {7884B635-79EE-4F4F-A2E6-351DC4FFE5D1}.Release|x64.ActiveCfg = Release|x64 + {7884B635-79EE-4F4F-A2E6-351DC4FFE5D1}.Release|x64.Build.0 = Release|x64 + {7884B635-79EE-4F4F-A2E6-351DC4FFE5D1}.Release|x86.ActiveCfg = Release|Win32 + {7884B635-79EE-4F4F-A2E6-351DC4FFE5D1}.Release|x86.Build.0 = Release|Win32 + {7DB572DF-1CA8-43EA-AF0B-286ABBF0EAEA}.Debug|x64.ActiveCfg = Debug|x64 + {7DB572DF-1CA8-43EA-AF0B-286ABBF0EAEA}.Debug|x64.Build.0 = Debug|x64 + {7DB572DF-1CA8-43EA-AF0B-286ABBF0EAEA}.Debug|x86.ActiveCfg = Debug|Win32 + {7DB572DF-1CA8-43EA-AF0B-286ABBF0EAEA}.Debug|x86.Build.0 = Debug|Win32 + {7DB572DF-1CA8-43EA-AF0B-286ABBF0EAEA}.Release|x64.ActiveCfg = Release|x64 + {7DB572DF-1CA8-43EA-AF0B-286ABBF0EAEA}.Release|x64.Build.0 = Release|x64 + {7DB572DF-1CA8-43EA-AF0B-286ABBF0EAEA}.Release|x86.ActiveCfg = Release|Win32 + {7DB572DF-1CA8-43EA-AF0B-286ABBF0EAEA}.Release|x86.Build.0 = Release|Win32 + {F5008C52-3846-4E97-A2E2-469151020F32}.Debug|x64.ActiveCfg = Debug|x64 + {F5008C52-3846-4E97-A2E2-469151020F32}.Debug|x64.Build.0 = Debug|x64 + {F5008C52-3846-4E97-A2E2-469151020F32}.Debug|x86.ActiveCfg = Debug|Win32 + {F5008C52-3846-4E97-A2E2-469151020F32}.Debug|x86.Build.0 = Debug|Win32 + {F5008C52-3846-4E97-A2E2-469151020F32}.Release|x64.ActiveCfg = Release|x64 + {F5008C52-3846-4E97-A2E2-469151020F32}.Release|x64.Build.0 = Release|x64 + {F5008C52-3846-4E97-A2E2-469151020F32}.Release|x86.ActiveCfg = Release|Win32 + {F5008C52-3846-4E97-A2E2-469151020F32}.Release|x86.Build.0 = Release|Win32 + {A750850B-D551-4A7A-BD85-A43EAC09B457}.Debug|x64.ActiveCfg = Debug|x64 + {A750850B-D551-4A7A-BD85-A43EAC09B457}.Debug|x64.Build.0 = Debug|x64 + {A750850B-D551-4A7A-BD85-A43EAC09B457}.Debug|x86.ActiveCfg = Debug|Win32 + {A750850B-D551-4A7A-BD85-A43EAC09B457}.Debug|x86.Build.0 = Debug|Win32 + {A750850B-D551-4A7A-BD85-A43EAC09B457}.Release|x64.ActiveCfg = Release|x64 + {A750850B-D551-4A7A-BD85-A43EAC09B457}.Release|x64.Build.0 = Release|x64 + {A750850B-D551-4A7A-BD85-A43EAC09B457}.Release|x86.ActiveCfg = Release|Win32 + {A750850B-D551-4A7A-BD85-A43EAC09B457}.Release|x86.Build.0 = Release|Win32 + {5A75B594-5757-46A0-A498-7988EFFD2FDD}.Debug|x64.ActiveCfg = Debug|x64 + {5A75B594-5757-46A0-A498-7988EFFD2FDD}.Debug|x64.Build.0 = Debug|x64 + {5A75B594-5757-46A0-A498-7988EFFD2FDD}.Debug|x86.ActiveCfg = Debug|Win32 + {5A75B594-5757-46A0-A498-7988EFFD2FDD}.Debug|x86.Build.0 = Debug|Win32 + {5A75B594-5757-46A0-A498-7988EFFD2FDD}.Release|x64.ActiveCfg = Release|x64 + {5A75B594-5757-46A0-A498-7988EFFD2FDD}.Release|x64.Build.0 = Release|x64 + {5A75B594-5757-46A0-A498-7988EFFD2FDD}.Release|x86.ActiveCfg = Release|Win32 + {5A75B594-5757-46A0-A498-7988EFFD2FDD}.Release|x86.Build.0 = Release|Win32 + {DB51624F-B4D2-454B-B82D-01C1A1DA44A8}.Debug|x64.ActiveCfg = Debug|x64 + {DB51624F-B4D2-454B-B82D-01C1A1DA44A8}.Debug|x64.Build.0 = Debug|x64 + {DB51624F-B4D2-454B-B82D-01C1A1DA44A8}.Debug|x86.ActiveCfg = Debug|Win32 + {DB51624F-B4D2-454B-B82D-01C1A1DA44A8}.Debug|x86.Build.0 = Debug|Win32 + {DB51624F-B4D2-454B-B82D-01C1A1DA44A8}.Release|x64.ActiveCfg = Release|x64 + {DB51624F-B4D2-454B-B82D-01C1A1DA44A8}.Release|x64.Build.0 = Release|x64 + {DB51624F-B4D2-454B-B82D-01C1A1DA44A8}.Release|x86.ActiveCfg = Release|Win32 + {DB51624F-B4D2-454B-B82D-01C1A1DA44A8}.Release|x86.Build.0 = Release|Win32 + {A0279F67-6D8F-404F-9D13-76538301E683}.Debug|x64.ActiveCfg = Debug|x64 + {A0279F67-6D8F-404F-9D13-76538301E683}.Debug|x64.Build.0 = Debug|x64 + {A0279F67-6D8F-404F-9D13-76538301E683}.Debug|x86.ActiveCfg = Debug|Win32 + {A0279F67-6D8F-404F-9D13-76538301E683}.Debug|x86.Build.0 = Debug|Win32 + {A0279F67-6D8F-404F-9D13-76538301E683}.Release|x64.ActiveCfg = Release|x64 + {A0279F67-6D8F-404F-9D13-76538301E683}.Release|x64.Build.0 = Release|x64 + {A0279F67-6D8F-404F-9D13-76538301E683}.Release|x86.ActiveCfg = Release|Win32 + {A0279F67-6D8F-404F-9D13-76538301E683}.Release|x86.Build.0 = Release|Win32 + {D065D515-FA81-46F1-9BF5-2BD8830B379A}.Debug|x64.ActiveCfg = Debug|x64 + {D065D515-FA81-46F1-9BF5-2BD8830B379A}.Debug|x64.Build.0 = Debug|x64 + {D065D515-FA81-46F1-9BF5-2BD8830B379A}.Debug|x86.ActiveCfg = Debug|Win32 + {D065D515-FA81-46F1-9BF5-2BD8830B379A}.Debug|x86.Build.0 = Debug|Win32 + {D065D515-FA81-46F1-9BF5-2BD8830B379A}.Release|x64.ActiveCfg = Release|x64 + {D065D515-FA81-46F1-9BF5-2BD8830B379A}.Release|x64.Build.0 = Release|x64 + {D065D515-FA81-46F1-9BF5-2BD8830B379A}.Release|x86.ActiveCfg = Release|Win32 + {D065D515-FA81-46F1-9BF5-2BD8830B379A}.Release|x86.Build.0 = Release|Win32 + {2BE54595-4B99-4E0C-B743-FBC00E7D8082}.Debug|x64.ActiveCfg = Debug|x64 + {2BE54595-4B99-4E0C-B743-FBC00E7D8082}.Debug|x64.Build.0 = Debug|x64 + {2BE54595-4B99-4E0C-B743-FBC00E7D8082}.Debug|x86.ActiveCfg = Debug|Win32 + {2BE54595-4B99-4E0C-B743-FBC00E7D8082}.Debug|x86.Build.0 = Debug|Win32 + {2BE54595-4B99-4E0C-B743-FBC00E7D8082}.Release|x64.ActiveCfg = Release|x64 + {2BE54595-4B99-4E0C-B743-FBC00E7D8082}.Release|x64.Build.0 = Release|x64 + {2BE54595-4B99-4E0C-B743-FBC00E7D8082}.Release|x86.ActiveCfg = Release|Win32 + {2BE54595-4B99-4E0C-B743-FBC00E7D8082}.Release|x86.Build.0 = Release|Win32 + {2ACA60C6-E8F1-4B5D-9088-5A95F6813C0F}.Debug|x64.ActiveCfg = Debug|x64 + {2ACA60C6-E8F1-4B5D-9088-5A95F6813C0F}.Debug|x64.Build.0 = Debug|x64 + {2ACA60C6-E8F1-4B5D-9088-5A95F6813C0F}.Debug|x86.ActiveCfg = Debug|Win32 + {2ACA60C6-E8F1-4B5D-9088-5A95F6813C0F}.Debug|x86.Build.0 = Debug|Win32 + {2ACA60C6-E8F1-4B5D-9088-5A95F6813C0F}.Release|x64.ActiveCfg = Release|x64 + {2ACA60C6-E8F1-4B5D-9088-5A95F6813C0F}.Release|x64.Build.0 = Release|x64 + {2ACA60C6-E8F1-4B5D-9088-5A95F6813C0F}.Release|x86.ActiveCfg = Release|Win32 + {2ACA60C6-E8F1-4B5D-9088-5A95F6813C0F}.Release|x86.Build.0 = Release|Win32 + {56B453EF-BD2A-4165-A834-17EB2C3FA0B1}.Debug|x64.ActiveCfg = Debug|x64 + {56B453EF-BD2A-4165-A834-17EB2C3FA0B1}.Debug|x64.Build.0 = Debug|x64 + {56B453EF-BD2A-4165-A834-17EB2C3FA0B1}.Debug|x86.ActiveCfg = Debug|Win32 + {56B453EF-BD2A-4165-A834-17EB2C3FA0B1}.Debug|x86.Build.0 = Debug|Win32 + {56B453EF-BD2A-4165-A834-17EB2C3FA0B1}.Release|x64.ActiveCfg = Release|x64 + {56B453EF-BD2A-4165-A834-17EB2C3FA0B1}.Release|x64.Build.0 = Release|x64 + {56B453EF-BD2A-4165-A834-17EB2C3FA0B1}.Release|x86.ActiveCfg = Release|Win32 + {56B453EF-BD2A-4165-A834-17EB2C3FA0B1}.Release|x86.Build.0 = Release|Win32 + {9633BE9A-131A-453E-9AB9-CE77AEE9F72C}.Debug|x64.ActiveCfg = Debug|x64 + {9633BE9A-131A-453E-9AB9-CE77AEE9F72C}.Debug|x64.Build.0 = Debug|x64 + {9633BE9A-131A-453E-9AB9-CE77AEE9F72C}.Debug|x86.ActiveCfg = Debug|Win32 + {9633BE9A-131A-453E-9AB9-CE77AEE9F72C}.Debug|x86.Build.0 = Debug|Win32 + {9633BE9A-131A-453E-9AB9-CE77AEE9F72C}.Release|x64.ActiveCfg = Release|x64 + {9633BE9A-131A-453E-9AB9-CE77AEE9F72C}.Release|x64.Build.0 = Release|x64 + {9633BE9A-131A-453E-9AB9-CE77AEE9F72C}.Release|x86.ActiveCfg = Release|Win32 + {9633BE9A-131A-453E-9AB9-CE77AEE9F72C}.Release|x86.Build.0 = Release|Win32 + {AF82561F-B596-4032-9674-A3D22BFCE7F0}.Debug|x64.ActiveCfg = Debug|x64 + {AF82561F-B596-4032-9674-A3D22BFCE7F0}.Debug|x64.Build.0 = Debug|x64 + {AF82561F-B596-4032-9674-A3D22BFCE7F0}.Debug|x86.ActiveCfg = Debug|Win32 + {AF82561F-B596-4032-9674-A3D22BFCE7F0}.Debug|x86.Build.0 = Debug|Win32 + {AF82561F-B596-4032-9674-A3D22BFCE7F0}.Release|x64.ActiveCfg = Release|x64 + {AF82561F-B596-4032-9674-A3D22BFCE7F0}.Release|x64.Build.0 = Release|x64 + {AF82561F-B596-4032-9674-A3D22BFCE7F0}.Release|x86.ActiveCfg = Release|Win32 + {AF82561F-B596-4032-9674-A3D22BFCE7F0}.Release|x86.Build.0 = Release|Win32 + {65D4408B-2D18-48B4-8132-63A0420E86DD}.Debug|x64.ActiveCfg = Debug|x64 + {65D4408B-2D18-48B4-8132-63A0420E86DD}.Debug|x64.Build.0 = Debug|x64 + {65D4408B-2D18-48B4-8132-63A0420E86DD}.Debug|x86.ActiveCfg = Debug|Win32 + {65D4408B-2D18-48B4-8132-63A0420E86DD}.Debug|x86.Build.0 = Debug|Win32 + {65D4408B-2D18-48B4-8132-63A0420E86DD}.Release|x64.ActiveCfg = Release|x64 + {65D4408B-2D18-48B4-8132-63A0420E86DD}.Release|x64.Build.0 = Release|x64 + {65D4408B-2D18-48B4-8132-63A0420E86DD}.Release|x86.ActiveCfg = Release|Win32 + {65D4408B-2D18-48B4-8132-63A0420E86DD}.Release|x86.Build.0 = Release|Win32 + {F39996B4-EC69-4E59-BF5C-2CEA4E0E679A}.Debug|x64.ActiveCfg = Debug|x64 + {F39996B4-EC69-4E59-BF5C-2CEA4E0E679A}.Debug|x64.Build.0 = Debug|x64 + {F39996B4-EC69-4E59-BF5C-2CEA4E0E679A}.Debug|x86.ActiveCfg = Debug|Win32 + {F39996B4-EC69-4E59-BF5C-2CEA4E0E679A}.Debug|x86.Build.0 = Debug|Win32 + {F39996B4-EC69-4E59-BF5C-2CEA4E0E679A}.Release|x64.ActiveCfg = Release|x64 + {F39996B4-EC69-4E59-BF5C-2CEA4E0E679A}.Release|x64.Build.0 = Release|x64 + {F39996B4-EC69-4E59-BF5C-2CEA4E0E679A}.Release|x86.ActiveCfg = Release|Win32 + {F39996B4-EC69-4E59-BF5C-2CEA4E0E679A}.Release|x86.Build.0 = Release|Win32 + {F7878B46-CB83-44D9-B1B2-D90590B4A956}.Debug|x64.ActiveCfg = Debug|x64 + {F7878B46-CB83-44D9-B1B2-D90590B4A956}.Debug|x64.Build.0 = Debug|x64 + {F7878B46-CB83-44D9-B1B2-D90590B4A956}.Debug|x86.ActiveCfg = Debug|Win32 + {F7878B46-CB83-44D9-B1B2-D90590B4A956}.Debug|x86.Build.0 = Debug|Win32 + {F7878B46-CB83-44D9-B1B2-D90590B4A956}.Release|x64.ActiveCfg = Release|x64 + {F7878B46-CB83-44D9-B1B2-D90590B4A956}.Release|x64.Build.0 = Release|x64 + {F7878B46-CB83-44D9-B1B2-D90590B4A956}.Release|x86.ActiveCfg = Release|Win32 + {F7878B46-CB83-44D9-B1B2-D90590B4A956}.Release|x86.Build.0 = Release|Win32 + {C0A60136-A1C2-456A-9D52-1AC63AE70566}.Debug|x64.ActiveCfg = Debug|x64 + {C0A60136-A1C2-456A-9D52-1AC63AE70566}.Debug|x64.Build.0 = Debug|x64 + {C0A60136-A1C2-456A-9D52-1AC63AE70566}.Debug|x86.ActiveCfg = Debug|Win32 + {C0A60136-A1C2-456A-9D52-1AC63AE70566}.Debug|x86.Build.0 = Debug|Win32 + {C0A60136-A1C2-456A-9D52-1AC63AE70566}.Release|x64.ActiveCfg = Release|x64 + {C0A60136-A1C2-456A-9D52-1AC63AE70566}.Release|x64.Build.0 = Release|x64 + {C0A60136-A1C2-456A-9D52-1AC63AE70566}.Release|x86.ActiveCfg = Release|Win32 + {C0A60136-A1C2-456A-9D52-1AC63AE70566}.Release|x86.Build.0 = Release|Win32 + {3AF88D29-3590-4579-9ED6-FFF8F2311456}.Debug|x64.ActiveCfg = Debug|x64 + {3AF88D29-3590-4579-9ED6-FFF8F2311456}.Debug|x64.Build.0 = Debug|x64 + {3AF88D29-3590-4579-9ED6-FFF8F2311456}.Debug|x86.ActiveCfg = Debug|Win32 + {3AF88D29-3590-4579-9ED6-FFF8F2311456}.Debug|x86.Build.0 = Debug|Win32 + {3AF88D29-3590-4579-9ED6-FFF8F2311456}.Release|x64.ActiveCfg = Release|x64 + {3AF88D29-3590-4579-9ED6-FFF8F2311456}.Release|x64.Build.0 = Release|x64 + {3AF88D29-3590-4579-9ED6-FFF8F2311456}.Release|x86.ActiveCfg = Release|Win32 + {3AF88D29-3590-4579-9ED6-FFF8F2311456}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {4B60F505-AB1B-41D9-B844-9154DF64D5B4} + EndGlobalSection +EndGlobal diff --git a/msvc/apSurfaceSample/apSurfaceSample.vcxproj b/msvc/apSurfaceSample/apSurfaceSample.vcxproj new file mode 100644 index 0000000..f0f7517 --- /dev/null +++ b/msvc/apSurfaceSample/apSurfaceSample.vcxproj @@ -0,0 +1,130 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {65D4408B-2D18-48B4-8132-63A0420E86DD} + apSurfaceSample + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + DynamicLibrary + true + v140 + MultiByte + + + DynamicLibrary + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + Disabled + true + true + true + + + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/apSurfaceSample/apSurfaceSample.vcxproj.filters b/msvc/apSurfaceSample/apSurfaceSample.vcxproj.filters new file mode 100644 index 0000000..0b38de5 --- /dev/null +++ b/msvc/apSurfaceSample/apSurfaceSample.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/msvc/apSurfaceSample/apSurfaceSample.vcxproj.user b/msvc/apSurfaceSample/apSurfaceSample.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/msvc/apSurfaceSample/apSurfaceSample.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/msvc/apUvRange/apUvRange.vcxproj b/msvc/apUvRange/apUvRange.vcxproj new file mode 100644 index 0000000..fb3fd04 --- /dev/null +++ b/msvc/apUvRange/apUvRange.vcxproj @@ -0,0 +1,125 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {7DB572DF-1CA8-43EA-AF0B-286ABBF0EAEA} + apUvRange + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + DynamicLibrary + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/apUvRange/apUvRange.vcxproj.filters b/msvc/apUvRange/apUvRange.vcxproj.filters new file mode 100644 index 0000000..b220018 --- /dev/null +++ b/msvc/apUvRange/apUvRange.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/msvc/apUvRange/apUvRange.vcxproj.user b/msvc/apUvRange/apUvRange.vcxproj.user new file mode 100644 index 0000000..abe8dd8 --- /dev/null +++ b/msvc/apUvRange/apUvRange.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/msvc/apVolume/apVolume.vcxproj b/msvc/apVolume/apVolume.vcxproj new file mode 100644 index 0000000..debf6e1 --- /dev/null +++ b/msvc/apVolume/apVolume.vcxproj @@ -0,0 +1,132 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {3AF88D29-3590-4579-9ED6-FFF8F2311456} + apVolume + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + DynamicLibrary + true + v140 + MultiByte + + + DynamicLibrary + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + false + D:\library\vc14.0\openvdb-7.0.0\include;D:\library\vc14.0\openexr\include;D:\library\vc14.0\boost\include;D:\library\vc14.0\zlib\include;D:\library\vc14.0\c-blosc\include;D:\library\vc14.0\nanovdb\include;%(AdditionalIncludeDirectories) + OPENVDB_PRIVATE;OPENVDB_OPENEXR_STATICLIB;NDEBUG;%(PreprocessorDefinitions) + + + true + true + libopenvdb.lib;zlibstatic.lib;libblosc.lib;Half.lib;%(AdditionalDependencies) + D:\library\vc14.0\openvdb-7.0.0\lib;D:\library\vc14.0\zlib\lib;D:\library\vc14.0\c-blosc\lib;D:\library\vc14.0\openexr\lib;D:\library\vc14.0\boost\lib;%(AdditionalLibraryDirectories) + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/apVolume/apVolume.vcxproj.filters b/msvc/apVolume/apVolume.vcxproj.filters new file mode 100644 index 0000000..84096be --- /dev/null +++ b/msvc/apVolume/apVolume.vcxproj.filters @@ -0,0 +1,38 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + + + Resource Files + + + + + Header Files + + + \ No newline at end of file diff --git a/msvc/apVolume/apVolume.vcxproj.user b/msvc/apVolume/apVolume.vcxproj.user new file mode 100644 index 0000000..a11cd7f --- /dev/null +++ b/msvc/apVolume/apVolume.vcxproj.user @@ -0,0 +1,6 @@ + + + + true + + \ No newline at end of file diff --git a/msvc/apZinkeBSDF/apZinkeBSDF.vcxproj b/msvc/apZinkeBSDF/apZinkeBSDF.vcxproj new file mode 100644 index 0000000..0689b91 --- /dev/null +++ b/msvc/apZinkeBSDF/apZinkeBSDF.vcxproj @@ -0,0 +1,130 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {9633BE9A-131A-453E-9AB9-CE77AEE9F72C} + apZinkeBSDF + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + DynamicLibrary + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/msvc/apZinkeBSDF/apZinkeBSDF.vcxproj.filters b/msvc/apZinkeBSDF/apZinkeBSDF.vcxproj.filters new file mode 100644 index 0000000..041c001 --- /dev/null +++ b/msvc/apZinkeBSDF/apZinkeBSDF.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/msvc/arnold.props b/msvc/arnold.props new file mode 100644 index 0000000..d0711e4 --- /dev/null +++ b/msvc/arnold.props @@ -0,0 +1,49 @@ + + + + + D:\library\external + 5.1.1.1 + $(ARNOLD_ROOT)\Arnold-$(ARNOLD_VER) + C:\solidangle\mtoadeploy + $(MTOA_ROOT)\$(MAYA_VER) + + + <_PropertySheetDisplayName>Arnold SDK + .dll + + + + $(ARNOLD_LOCATION)\include;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS + Disabled + + + $(ARNOLD_LOCATION)\lib;%(AdditionalLibraryDirectories) + ai.lib;%(AdditionalDependencies) + Windows + DebugFastLink + + + copy $(TargetPath) $(solutionDir)..\build\$(solutionName)\shaders /Y/B +$(SolutionDir)..\cmd\post_build_shader.bat $(SolutionName) $(ProjectName) $(TargetPath) $(solutionDir)..\build\$(solutionName) + + + + + $(ARNOLD_ROOT) + + + $(ARNOLD_VER) + + + $(ARNOLD_LOCATION) + + + $(MTOA_ROOT) + + + $(MTOA_LOCATION) + + + \ No newline at end of file diff --git a/src/.env b/src/.env new file mode 100644 index 0000000..a9a1a92 --- /dev/null +++ b/src/.env @@ -0,0 +1 @@ +PYTHONPATH=C:\Autodesk\mtoa\4.2.4\2020\scripts \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..6d1992e --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,17 @@ +add_subdirectory(apBoolean) +add_subdirectory(apChaosMosaic) +add_subdirectory(apCurveSample) +# add_subdirectory(apClosure) +add_subdirectory(apEntrySwitch) +add_subdirectory(apGrayBall) +# add_subdirectory(apHairBSDF) +add_subdirectory(apInteriorMapping) +# add_subdirectory(apMetalBSDF) +# add_subdirectory(apMicrofacetBSDF) +# add_subdirectory(apMicrofacetRefractionBSDF) +# add_subdirectory(apOrenNayerBSDF) +add_subdirectory(apParallaxMap) +add_subdirectory(apSurfaceSample) +add_subdirectory(apUvRange) +add_subdirectory(apCrossBlend) +add_subdirectory(apTextureRandom) \ No newline at end of file diff --git a/src/apBoolean/CMakeLists.txt b/src/apBoolean/CMakeLists.txt new file mode 100644 index 0000000..c611a2d --- /dev/null +++ b/src/apBoolean/CMakeLists.txt @@ -0,0 +1,18 @@ +set(SHADER apBoolean) + +set(SRC_FILES + "apBoolean.cpp") + +set(META_FILES + "apBoolean.mtd") + +include_directories(${ARNOLD_INCLUDE_PATH}) +add_library(${SHADER} SHARED ${SRC_FILES}) +set_target_properties(${SHADER} PROPERTIES PREFIX "") + +target_link_libraries(${SHADER} ${ARNOLD_AI_LIBRARY}) + +set(INSTALL_SHADER_TARGET "${CMAKE_INSTALL_PREFIX}/${ARNOLD_VERSION}/${CMAKE_PROJECT_NAME}/shaders") + +install(TARGETS ${SHADER} RUNTIME DESTINATION ${INSTALL_SHADER_TARGET}) +install(FILES ${META_FILES} DESTINATION ${INSTALL_SHADER_TARGET}) \ No newline at end of file diff --git a/src/apBoolean/apBoolean.cpp b/src/apBoolean/apBoolean.cpp new file mode 100644 index 0000000..b954dda --- /dev/null +++ b/src/apBoolean/apBoolean.cpp @@ -0,0 +1,552 @@ +#include "ai.h" +#include + +using namespace std; + +AI_SHADER_NODE_EXPORT_METHODS(apBoolean) + +enum BooleaOp { + kUnion = 0, + kDifference, + kIntersection +}; + +enum apBooleanParams { + p_operator, + p_object_a, + p_set_a, + p_shader_a, + p_object_b, + p_set_b, + p_shader_b, + p_swap, + p_max_depth +}; + +static const char* OperatorNames[] = { + "Union (A+B)", + "Difference (A-B)", + "Intersection (A & B)", + NULL +}; + +struct ShaderData +{ + int boolean_operator; + bool swap; + int max_depth; +}; + +typedef struct +{ + bool inside_a; + bool inside_b; + bool p_inside_a; + bool p_inside_b; + +} RayState; + +node_parameters +{ + AiParameterEnum("operator", 0, OperatorNames); + AiParameterNode("object_a", NULL); + AiParameterStr("trace_set_a", ""); + AiParameterClosure("shader_a"); + AiParameterNode("object_b", NULL); + AiParameterStr("trace_set_b", ""); + AiParameterClosure("shader_b"); + AiParameterBool("swap", false); + AiParameterInt("max_depth", 10); +} + +node_initialize +{ + ShaderData *data = new ShaderData; + AiNodeSetLocalData(node, data); +} + +node_update +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); +} + +node_finish +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AiFree(data); +} + +shader_evaluate +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + + int bop = AiShaderEvalParamBool(p_operator); + bool swap = AiShaderEvalParamBool(p_swap); + int max_depth = AiShaderEvalParamInt(p_max_depth); + + AtNode *object_a = (AtNode *)AiShaderEvalParamPtr(p_object_a); + AtClosureList closure_a = AiShaderEvalParamClosure(p_shader_a); + AtString object_a_name(AiNodeGetName(object_a)); + //AiMsgInfo("A: %s", object_a_name.c_str()); + + AtNode *object_b = (AtNode *)AiShaderEvalParamPtr(p_object_b); + AtClosureList closure_b = AiShaderEvalParamClosure(p_shader_b); + AtString object_b_name(AiNodeGetName(object_b)); + //AiMsgInfo("B: %s", object_b_name.c_str()); + AtNode *object = sg->Op; + AtString object_name(AiNodeGetName(object)); + + bool inv_normal = AiV3Dot(-sg->Rd, sg->N) < 0; + + if (sg->Rt & AI_RAY_SHADOW) { + + // First shadow call + int first_shadow, cur_first_shadow; + //int cur_first_shadow = AiStateGetMsgInt(AtString("first_shadow"), &first_shadow) ? 0 : 1; + if (AiStateGetMsgInt(AtString("first_shadow"), &first_shadow)) + cur_first_shadow = 0; + else + cur_first_shadow = 1; + + AiStateSetMsgInt(AtString("first_shadow"), cur_first_shadow); + + //cg_mat + bool inside_a; + bool inside_b; + bool p_inside_a; + bool p_inside_b; + + /*RayState *shadow_state; + RayState csg_mat; + if (!AiStateGetMsgPtr(AtString("shadow_state"), (void**)&shadow_state)) + { + csg_mat = *shadow_state; + }*/ + + // Initialize it + if (!AiStateGetMsgBool(AtString("inside_a"), &inside_a)) + inside_a = false; + if (!AiStateGetMsgBool(AtString("inside_b"), &inside_a)) + inside_b = false; + if (!AiStateGetMsgBool(AtString("p_inside_a"), &p_inside_a)) + p_inside_a = false; + if (!AiStateGetMsgBool(AtString("p_inside_b"), &p_inside_a)) + p_inside_b = false; + + if (cur_first_shadow > 0) { + if (object_name == object_a_name) + if (!AiV3Dot(sg->Rd, sg->psg->Ng)) + inside_a = true; + if (object_name == object_b_name) + if (!AiV3Dot(sg->Rd, sg->psg->Ng)) + inside_b = true; + } + + bool inside_a_shadow; + bool inside_b_shadow; + bool p_inside_a_shadow; + bool p_inside_b_shadow; + + if (!AiStateGetMsgBool(AtString("inside_a_shadow"), &inside_a_shadow)) + inside_a_shadow = false; + if (!AiStateGetMsgBool(AtString("inside_b_shadow"), &inside_b_shadow)) + inside_b_shadow = false; + if (!AiStateGetMsgBool(AtString("p_inside_a_shadow"), &p_inside_a_shadow)) + p_inside_a_shadow = false; + if (!AiStateGetMsgBool(AtString("p_inside_b_shadow"), &p_inside_b_shadow)) + p_inside_a_shadow = false; + + AtRGB shadow_transparency = AI_RGB_ZERO; + + if (bop == BooleaOp::kUnion) { + AtClosureList closures; + closures.add(AiClosureTransparent(sg, AI_RGB_ZERO)); + sg->out.CLOSURE() = closures; + return; + } + + if (bop == BooleaOp::kDifference) { + + if (cur_first_shadow > 0) + { + if (AiV3Dot(sg->Rd, sg->Ng) && (inside_a || inside_b)) + { + inside_a = p_inside_a; + inside_b = p_inside_b; + } + + if (inside_a && inside_b) //inside A & B + { + + if (object_name == object_a_name) + { + AiStateSetMsgBool(AtString("inside_a_shadow"), (inv_normal) ? false : true); + AtClosureList closures; + closures.add(AiClosureTransparent(sg, AI_RGB_ZERO)); + sg->out.CLOSURE() = closures; + return; + } + if (object_name == object_b_name) + { + AiStateSetMsgBool(AtString("inside_b_shadow"), (inv_normal) ? false : true); + + /*AtScrSample shadow_sample; + AtRay ray = AiMakeRay(AI_RAY_SHADOW, sg->P, &sg->Rd, AI_INFINITE, sg); + + if (AiTrace(ray, AI_RGB_WHITE, shadow_sample)) + { + AtClosureList closures; + closures.add(AiClosureTransparent(sg, shadow_sample.opacity)); + sg->out.CLOSURE() = closures; + }*/ + AtClosureList closures; + closures.add(AiClosureTransparent(sg, AI_RGB_WHITE)); + sg->out.CLOSURE() = closures; + return; + } + // Not match any object names + AtClosureList closures; + closures.add(AiClosureTransparent(sg, AI_RGB_ZERO)); + sg->out.CLOSURE() = closures; + return; + } + + if (inside_a) + { + if (object_name == object_a_name || object_name == object_b_name) + { + if (object_name == object_a_name) + AiStateSetMsgBool(AtString("inside_a_shadow"), (inv_normal) ? false : true); + + if (object_name == object_b_name) + AiStateSetMsgBool(AtString("inside_b_shadow"), (inv_normal) ? false : true); + + /*AtScrSample shadow_sample; + AtRay ray = AiMakeRay(AI_RAY_SHADOW, sg->P, &sg->Rd, AI_INFINITE, sg); + + if (AiTrace(ray, AI_RGB_WHITE, shadow_sample)) + { + AtClosureList closures; + closures.add(AiClosureTransparent(sg, shadow_sample.opacity)); + sg->out.CLOSURE() = closures; + }*/ + AtClosureList closures; + closures.add(AiClosureTransparent(sg, AI_RGB_WHITE)); + sg->out.CLOSURE() = closures; + } + return; + } + + if (inside_b) + { + if (object_name == object_b_name || object_name == object_a_name) + { + if (object_name == object_b_name) + AiStateSetMsgBool(AtString("inside_b_shadow"), (inv_normal) ? false : true); + + if (object_name == object_a_name) + AiStateSetMsgBool(AtString("inside_a_shadow"), (inv_normal) ? false : true); + + AtClosureList closures; + closures.add(AiClosureTransparent(sg, AI_RGB_ZERO)); + sg->out.CLOSURE() = closures; + } + return; + } + // + if (object_name == object_a_name) + { + AiStateSetMsgBool(AtString("inside_a_shadow"), (inv_normal) ? false : true); + /*AtScrSample shadow_sample; + AtRay ray = AiMakeRay(AI_RAY_SHADOW, sg->P, &sg->Rd, AI_INFINITE, sg); + if (AiTrace(ray, AI_RGB_WHITE, shadow_sample)) + { + AtClosureList closures; + closures.add(AiClosureTransparent(sg, shadow_sample.opacity)); + sg->out.CLOSURE() = closures; + }*/ + AtClosureList closures; + closures.add(AiClosureTransparent(sg, AI_RGB_WHITE)); + sg->out.CLOSURE() = closures; + } + else + { + AiStateSetMsgBool(AtString("inside_b_shadow"), (inv_normal) ? false : true); + AtClosureList closures; + closures.add(AiClosureTransparent(sg, AI_RGB_ZERO)); + sg->out.CLOSURE() = closures; + } + AtClosureList closures; + closures.add(AiClosureTransparent(sg, AI_RGB_WHITE)); + sg->out.CLOSURE() = closures; + return; + } + else // secondary shadow call + { + if (inside_a_shadow && inside_b_shadow) + { + if (object_name == object_a_name || object_name == object_b_name) + { + if (object_name == object_a_name) + AiStateSetMsgBool(AtString("inside_a_shadow"), AiV3Dot(sg->Rd, sg->Ng) ? false : true); + + if (object_name == object_b_name) + AiStateSetMsgBool(AtString("inside_b_shadow"), AiV3Dot(sg->Rd, sg->Ng) ? false : true); + } + AtClosureList closures; + closures.add(AiClosureTransparent(sg, AI_RGB_ZERO)); + sg->out.CLOSURE() = closures; + return; + } + + // inside A + if (inside_a_shadow) + { + if (object_name == object_a_name) + { + AiStateSetMsgBool(AtString("inside_a_shadow"), AiV3Dot(sg->Rd, sg->Ng) ? false : true); + /*AtScrSample shadow_sample; + AtRay ray = AiMakeRay(AI_RAY_SHADOW, sg->P, &sg->Rd, AI_INFINITE, sg); + + if (AiTrace(ray, AI_RGB_WHITE, shadow_sample)) + { + AtClosureList closures; + closures.add(AiClosureTransparent(sg, shadow_sample.opacity)); + sg->out.CLOSURE() = closures; + }*/ + AtClosureList closures; + closures.add(AiClosureTransparent(sg, AI_RGB_WHITE)); + sg->out.CLOSURE() = closures; + + } + if (object_name == object_b_name) + { + AiStateSetMsgBool(AtString("inside_a_shadow"), AiV3Dot(sg->Rd, sg->Ng) ? false : true); + AtClosureList closures; + closures.add(AiClosureTransparent(sg, AI_RGB_ZERO)); + sg->out.CLOSURE() = closures; + } + return; + } + // inside B + if (inside_b_shadow) + { + if (object_name == object_a_name || object_name == object_b_name) + { + if (object_name == object_b_name) + { + AiStateSetMsgBool(AtString("inside_b_shadow"), AiV3Dot(sg->Rd, sg->Ng) ? false : true); + /*AtScrSample shadow_sample; + AtRay ray = AiMakeRay(AI_RAY_SHADOW, sg->P, &sg->Rd, AI_INFINITE, sg); + + if (AiTrace(ray, AI_RGB_WHITE, shadow_sample)) + { + AtClosureList closures; + closures.add(AiClosureTransparent(sg, shadow_sample.opacity)); + sg->out.CLOSURE() = closures; + }*/ + AtClosureList closures; + closures.add(AiClosureTransparent(sg, AI_RGB_WHITE)); + sg->out.CLOSURE() = closures; + } + if (object_name == object_a_name) + { + AiStateSetMsgBool(AtString("inside_a_shadow"), AiV3Dot(sg->Rd, sg->Ng) ? false : true); + AtClosureList closures; + closures.add(AiClosureTransparent(sg, AI_RGB_ZERO)); + sg->out.CLOSURE() = closures; + } + } + return; + } + // inside None + if (object_name == object_a_name) + { + AiStateSetMsgBool(AtString("inside_a_shadow"), AiV3Dot(sg->Rd, sg->Ng) ? false : true); + /*AtScrSample shadow_sample; + AtRay ray = AiMakeRay(AI_RAY_SHADOW, sg->P, &sg->Rd, AI_INFINITE, sg); + + if (AiTrace(ray, AI_RGB_WHITE, shadow_sample)) + { + AtClosureList closures; + closures.add(AiClosureTransparent(sg, shadow_sample.opacity)); + sg->out.CLOSURE() = closures; + }*/ + AtClosureList closures; + closures.add(AiClosureTransparent(sg, AI_RGB_WHITE)); + sg->out.CLOSURE() = closures; + return; + } + else + { + AiStateSetMsgBool(AtString("inside_b_shadow"), AiV3Dot(sg->Rd, sg->Ng) ? false : true); + AtClosureList closures; + closures.add(AiClosureTransparent(sg, AI_RGB_ZERO)); + sg->out.CLOSURE() = closures; + return; + } + AtClosureList closures; + closures.add(AiClosureTransparent(sg, AI_RGB_WHITE)); + sg->out.CLOSURE() = closures; + } + return; + } + AtClosureList closures; + //closures.add(AiClosureTransparent(sg, AI_RGB_ZERO)); + closures.add(AiClosureTransparent(sg, shadow_transparency)); + sg->out.CLOSURE() = closures; + return; + } + + bool inside_a = false; + bool inside_b = false; + + AiStateGetMsgBool(AtString("inside_a"), &inside_a); + AiStateGetMsgBool(AtString("inside_b"), &inside_b); + + // Union + if (bop == BooleaOp::kUnion) + { + if (inside_a && inside_b) + { + if (object_name == object_a_name) + AiStateSetMsgBool(AtString("inside_a"), (inv_normal) ? false : true); + else if (object_name == object_b_name) + AiStateSetMsgBool(AtString("inside_b"), (inv_normal) ? false : true); + else + { + AtClosureList closures; + closures.add(AiClosureEmission(sg, AI_RGB_RED)); + return; + } + AtClosureList closures; + closures.add(AiClosureTransparent(sg)); + sg->out.CLOSURE() = closures; + return; + } + else + { + if (inside_a) + { + if (object_name == object_a_name) + { + AiStateSetMsgBool(AtString("inside_a"), (inv_normal) ? false : true); + sg->out.CLOSURE() = closure_a; + return; + } + else + { + AiStateSetMsgBool(AtString("inside_b"), (inv_normal) ? false : true); + AtClosureList closures; + closures.add(AiClosureTransparent(sg)); + sg->out.CLOSURE() = closures; + return; + } + } + else + { + if (object_name == object_b_name) + { + } + } + } + } + // Difference + if (bop == BooleaOp::kDifference) { + // Inside A & B + if (inside_a == true && inside_b == true) + { + if (object_name == object_a_name) + { + AiStateSetMsgBool(AtString("inside_a"), (inv_normal) ? false : true); + sg->out.CLOSURE() = closure_a; + return; + } + if (object_name == object_b_name) { + AiStateSetMsgBool(AtString("inside_b"), (inv_normal) ? false : true); + AtClosureList closures; + closures.add(AiClosureTransparent(sg)); + sg->out.CLOSURE() = closures; + return; + } + + } else { + // Inside A + if (inside_a) { + if (object_name == object_a_name) { + if (inv_normal) + AiStateSetMsgBool(AtString("inside_a"), false); + else + AiStateSetMsgBool(AtString("inside_a"), true); + AtClosureList closures; + closures.add(AiClosureTransparent(sg)); + sg->out.CLOSURE() = closures; + return; + + } else { + if (inv_normal) + AiStateSetMsgBool(AtString("inside_b"), false); + else + AiStateSetMsgBool(AtString("inside_b"), true); + AtClosureList closures; + closures.add(AiClosureTransparent(sg)); + sg->out.CLOSURE() = closures; + return; + } + } else { + // Inside B + if (inside_b) { + if (object_name == object_b_name) { + if (inv_normal) + AiStateSetMsgBool(AtString("inside_b"), false); + else + AiStateSetMsgBool(AtString("inside_b"), true); + sg->out.CLOSURE() = closure_b; + return; + + } else { + if (inv_normal) + AiStateSetMsgBool(AtString("inside_a"), false); + else + AiStateSetMsgBool(AtString("inside_a"), true); + sg->out.CLOSURE() = closure_a; + return; + } + + } else { + // Inside None + if (object_name == object_a_name) { + if (inv_normal == false) + AiStateSetMsgBool(AtString("inside_a"), true); + + AtClosureList closures; + closures.add(AiClosureTransparent(sg)); + sg->out.CLOSURE() = closures; + return; + } else { + if (inv_normal == false) + AiStateSetMsgBool(AtString("inside_b"), true); + sg->out.CLOSURE() = closure_b; + return; + } + } + } + } + } + if (bop == BooleaOp::kIntersection){ + + } + sg->out.CLOSURE() = AiClosureEmission(sg, AtRGB(1.0, 0, 0)); +} +node_loader +{ + if (i > 0) + return false; + + node->methods = apBoolean; + node->output_type = AI_TYPE_CLOSURE; + node->name = "apBoolean"; + node->node_type = AI_NODE_SHADER; + strcpy(node->version, AI_VERSION); + return true; +} \ No newline at end of file diff --git a/src/apBoolean/apBoolean.mtd b/src/apBoolean/apBoolean.mtd new file mode 100644 index 0000000..2232e9e --- /dev/null +++ b/src/apBoolean/apBoolean.mtd @@ -0,0 +1,42 @@ +[node apBoolean] + maya.name STRING "apBoolean" + maya.id INT 0x0005101 + maya.classification STRING "shader/surface" + [attr operator] + desc STRING "Boolean Operator" + maya.keyable BOOL false + linkable BOOL true + + [attr object_a] + desc STRING "Object A" + maya.keyable BOOL false + linkable BOOL true + + [attr trace_set_a] + maya.keyable BOOL false + linkable BOOL false + + [attr shader_a] + maya.keyable BOOL false + linkable BOOL true + + [attr object_b] + desc STRING "Object B" + maya.keyable BOOL false + linkable BOOL true + + [attr trace_set_b] + maya.keyable BOOL false + linkable BOOL false + + [attr shader_b] + maya.keyable BOOL false + linkable BOOL true + + [attr swap] + maya.keyable BOOL false + linkable BOOL true + + [attr max_depth] + maya.keyable BOOL false + linkable BOOL true \ No newline at end of file diff --git a/src/apChaosMosaic/CMakeLists.txt b/src/apChaosMosaic/CMakeLists.txt new file mode 100644 index 0000000..5bce692 --- /dev/null +++ b/src/apChaosMosaic/CMakeLists.txt @@ -0,0 +1,23 @@ +set(SHADER apChaosMosaic) + +set(SRC_FILES + "apChaosMosaic.cpp") + +set(META_FILES + "apChaosMosaic.mtd") + +set(TEMPLATE_FILES + "apChaosMosaicTemplate.py") + +include_directories(${ARNOLD_INCLUDE_PATH}) +add_library(${SHADER} SHARED ${SRC_FILES}) +set_target_properties(${SHADER} PROPERTIES PREFIX "") + +target_link_libraries(${SHADER} ${ARNOLD_AI_LIBRARY}) + +set(INSTALL_SHADER_TARGET "${CMAKE_INSTALL_PREFIX}/${ARNOLD_VERSION}/${CMAKE_PROJECT_NAME}/shaders") +set(INSTALL_TEMPLATE_TARGET "${CMAKE_INSTALL_PREFIX}/${ARNOLD_VERSION}/${CMAKE_PROJECT_NAME}/templates") + +install(TARGETS ${SHADER} RUNTIME DESTINATION ${INSTALL_SHADER_TARGET}) +install(FILES ${META_FILES} DESTINATION ${INSTALL_SHADER_TARGET}) +install(FILES ${TEMPLATE_FILES} DESTINATION ${INSTALL_TEMPLATE_TARGET}) \ No newline at end of file diff --git a/src/apChaosMosaic/apChaosMosaic.cpp b/src/apChaosMosaic/apChaosMosaic.cpp new file mode 100644 index 0000000..2988730 --- /dev/null +++ b/src/apChaosMosaic/apChaosMosaic.cpp @@ -0,0 +1,74 @@ +#include "ai.h" +#include +AI_SHADER_NODE_EXPORT_METHODS(apChaosMosaic) + +enum apChaosMosaicParams { + p_input, + p_tile +}; + +struct ShaderData +{ + int tile; +}; + +node_parameters +{ + AiParameterRGB("input", 0, 0, 0); + AiParameterInt("tile", 10); +} + +node_initialize +{ + ShaderData *data = (ShaderData *)AiMalloc(sizeof(ShaderData)); + AiNodeSetLocalData(node, data); +} + +node_update +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + data->tile = AiNodeGetInt(node, "tile"); +} + +node_finish +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AiFree(data); +} + +shader_evaluate +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + float x, y; + x = fmod(sg->u, 1); + y = fmod(sg->v, 1); + + float xi = floor(x*data->tile); + float yi = floor(y*data->tile); + + AtVector p(sg->u, sg->v, 0); + + float xp = AiCellNoise4(p, xi*data->tile + yi); + float yp = AiCellNoise4(p, xi*data->tile + yi + data->tile*data->tile); + float xoffset = fmod(fmod(x, 1.0 / data->tile) + xp, 1); + float yoffset = fmod(fmod(y, 1.0 / data->tile) + yp, 1); + + sg->u = xoffset; + sg->v = yoffset; + + sg->out.RGB() = AiShaderEvalParamRGB(p_input); + return; +} + +node_loader +{ + if (i > 0) + return false; + + node->methods = apChaosMosaic; + node->output_type = AI_TYPE_RGB; + node->name = "apChaosMosaic"; + node->node_type = AI_NODE_SHADER; + strcpy(node->version, AI_VERSION); + return true; +} diff --git a/src/apChaosMosaic/apChaosMosaic.mtd b/src/apChaosMosaic/apChaosMosaic.mtd new file mode 100644 index 0000000..ffeeba9 --- /dev/null +++ b/src/apChaosMosaic/apChaosMosaic.mtd @@ -0,0 +1,13 @@ +[node apChaosMosaic] + maya.name STRING "apChaosMosaic" + maya.id INT 0x0005104 + maya.classification STRING "texture/utility" + [attr input] + desc STRING "Input Texture" + maya.keyable BOOL false + linkable BOOL true + + [attr tile] + desc STRING "Tile" + maya.keyable BOOL false + linkable BOOL false diff --git a/src/apChaosMosaic/apChaosMosaicTemplate.py b/src/apChaosMosaic/apChaosMosaicTemplate.py new file mode 100644 index 0000000..e69de29 diff --git a/src/apClosure/apClosure.cpp b/src/apClosure/apClosure.cpp new file mode 100644 index 0000000..1e83484 --- /dev/null +++ b/src/apClosure/apClosure.cpp @@ -0,0 +1,88 @@ +#include "ai.h" + +AI_SHADER_NODE_EXPORT_METHODS(apClosure) + +enum apClosureParams +{ + p_input, + p_closure_type, + p_weight +}; + +static const char* ClosureNames[] = { + "Emission", + "Transparency", + "Matte", + "Background", + NULL +}; + +struct ShaderData +{ + int closure_type; +}; + +node_parameters +{ + AiParameterClosure("input"); + AiParameterEnum("closure_type", 0, ClosureNames); + AiParameterRGB("weight", 1, 1, 1); +} + +node_initialize +{ + ShaderData *data = (ShaderData *)AiMalloc(sizeof(ShaderData)); + AiNodeSetLocalData(node, data); +} + +node_update +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + data->closure_type = AiNodeGetInt(node, "closure_type"); +} + +node_finish +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AiFree(data); +} + +shader_evaluate +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AtRGB weight = AiShaderEvalParamRGB(p_weight); + + AtClosureList closures; + closures.add(AiShaderEvalParamClosure(p_input)); + + switch (data->closure_type) + { + case 0: + closures.add(AiClosureEmission(sg, weight)); + break; + case 1: + closures.add(AiClosureTransparent(sg, weight)); + break; + case 2: + closures.add(AiClosureMatte(sg, weight)); + break; + case 3: + closures.add(AiClosureBackground(sg, weight)); + break; + } + sg->out.CLOSURE() = closures; + return; +} + +node_loader +{ + if (i > 0) + return false; + + node->methods = apClosure; + node->output_type = AI_TYPE_CLOSURE; + node->name = "apClosure"; + node->node_type = AI_NODE_SHADER; + strcpy(node->version, AI_VERSION); + return true; +} \ No newline at end of file diff --git a/src/apClosure/apClosure.mtd b/src/apClosure/apClosure.mtd new file mode 100644 index 0000000..c34a587 --- /dev/null +++ b/src/apClosure/apClosure.mtd @@ -0,0 +1,19 @@ +[node apClosure] + maya.name STRING "apClosure" + maya.id INT 0x0005107 + maya.classification STRING "shader/surface" + [attr input] + desc STRING "Input Closure" + maya.keyable BOOL false + linkable BOOL true + + [attr operator] + desc STRING "Closure Type" + maya.keyable BOOL false + linkable BOOL false + + [attr object_a] + desc STRING "Weight" + maya.keyable BOOL false + linkable BOOL true + diff --git a/src/apClosure/apClosureTemplate.py b/src/apClosure/apClosureTemplate.py new file mode 100644 index 0000000..dbe1491 --- /dev/null +++ b/src/apClosure/apClosureTemplate.py @@ -0,0 +1,16 @@ +import maya.mel +from mtoa.ui.ae.shaderTemplate import ShaderAETemplate + +class AEapClosureTemplate(ShaderAETemplate): + def setup(self): + self.addSwatch() + self.beginScrollLayout() + self.beginLayout("Closure Attributes", collapse=False) + self.addControl('input', label='Input') + self.addControl('closure_type', label='Closure Type') + self.addControl('weight', label='Weight') + self.endLayout() + maya.mel.eval('AEdependNodeTemplate '+self.nodeName) + self.addExtraControls() + self.endScrollLayout() + \ No newline at end of file diff --git a/src/apCrossBlend/CMakeLists.txt b/src/apCrossBlend/CMakeLists.txt new file mode 100644 index 0000000..0655c97 --- /dev/null +++ b/src/apCrossBlend/CMakeLists.txt @@ -0,0 +1,23 @@ +project(apCrossBlend) + +set(SRC_FILES + "apCrossBlend.cpp") + +set(META_FILES + "apCrossBlend.mtd") + +set(TEMPLATE_FILES + "apCrossBlendTemplate.py") + +include_directories(${ARNOLD_INCLUDE_PATH}) +add_library(${PROJECT_NAME} SHARED ${SRC_FILES}) +set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "") + +target_link_libraries(${PROJECT_NAME} ${ARNOLD_AI_LIBRARY}) + +set(INSTALL_SHADER_TARGET "${CMAKE_INSTALL_PREFIX}/${ARNOLD_VERSION}/${CMAKE_PROJECT_NAME}/shaders") +set(INSTALL_TEMPLATE_TARGET "${CMAKE_INSTALL_PREFIX}/${ARNOLD_VERSION}/${CMAKE_PROJECT_NAME}/templates") + +install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${INSTALL_SHADER_TARGET}) +install(FILES ${META_FILES} DESTINATION ${INSTALL_SHADER_TARGET}) +install(FILES ${TEMPLATE_FILES} DESTINATION ${INSTALL_TEMPLATE_TARGET}) \ No newline at end of file diff --git a/src/apCrossBlend/apCrossBlend.cpp b/src/apCrossBlend/apCrossBlend.cpp new file mode 100644 index 0000000..f597362 --- /dev/null +++ b/src/apCrossBlend/apCrossBlend.cpp @@ -0,0 +1,304 @@ +#include +#include +#include +#include +using namespace std; + +AI_SHADER_NODE_EXPORT_METHODS(apCrossBlend) +enum apCrossBlendParams +{ + p_surface, + p_enable, + p_ray_max_length, + p_ray_nsamples, + p_ray_min_dist, + p_ray_max_dist, + p_ray_max_depth, + p_trace_sets, + p_verbose, +}; + +struct ShaderData +{ + AtSampler *sampler; + bool enable; + float ray_max_length; + int ray_nsamples; + float ray_min_dist; + float ray_max_dist; + int ray_max_depth; + AtString trace_sets; + bool verbose; + const int seed = 3158863998; + const int ndim = 2; +}; + +struct SgCache +{ + SgCache(AtShaderGlobals *sg) + : sg(sg), + N(sg->N), + Ng(sg->Ng), + Ns(sg->Ns) + { + } + void restore() + { + sg->N = N; + sg->Ng = Ng; + sg->Ns = Ns; + } + AtShaderGlobals *sg; + AtVector N; + AtVector Ng; + AtVector Ns; +}; + +inline AtVector uniformSampleHemisphere(float u1, float u2) +{ + float y = u1; + float r = sqrtf(max(0.f, 1.f - y * y)); + float phi = 2 * AI_PI * u2; + float x = r * cosf(phi); + float z = r * sinf(phi); + return AtVector(x, y, z); +} + +inline void concentricSampleDisk(float u1, float u2, float &dx, float &dy) +{ + float r, theta; + // Map uniform random numbers to $[-1,1]^2$ + float sx = 2 * u1 - 1; + float sy = 2 * u2 - 1; + + // Map square to $(r,\theta)$ + + // Handle degeneracy at the origin + if (sx == 0.0 && sy == 0.0) + { + dx = 0.0; + dy = 0.0; + return; + } + if (sx >= -sy) + { + if (sx > sy) + { + // Handle first region of disk + r = sx; + if (sy > 0.0) + theta = sy / r; + else + theta = 8.0f + sy / r; + } + else + { + // Handle second region of disk + r = sy; + theta = 2.0f - sx / r; + } + } + else + { + if (sx <= sy) + { + // Handle third region of disk + r = -sx; + theta = 4.0f - sy / r; + } + else + { + // Handle fourth region of disk + r = -sy; + theta = 6.0f + sx / r; + } + } + theta *= float(AI_PI) / 4.f; + dx = r * cosf(theta); + dy = r * sinf(theta); +} + +node_parameters +{ + AiParameterClosure("surface"); + AiParameterBool("enable", true); + AiParameterFlt("ray_max_length", 1.0); + AiParameterInt("ray_nsamples", 64); + AiParameterFlt("ray_min_dist", 0.001); + AiParameterFlt("ray_max_dist", 1000); + AiParameterInt("ray_max_depth", 10); + AiParameterStr("trace_sets", ""); + AiParameterBool("verbose", true); +} + +node_initialize +{ + ShaderData *data = (ShaderData *)AiMalloc(sizeof(ShaderData)); + const int seed = 3158863998; + const int nsamples = AiNodeGetInt(node, "ray_nsamples"); + const int ndim = 2; + data->sampler = AiSampler(seed, nsamples, ndim); + AiNodeSetLocalData(node, data); +} + +node_finish +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AiSamplerDestroy(data->sampler); + AiFree(data); +} + +node_update +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + data->enable = AiNodeGetBool(node, "enable"); + data->ray_max_length = AiNodeGetFlt(node, "ray_max_length"); + data->ray_nsamples = AiNodeGetInt(node, "ray_nsamples"); + data->ray_min_dist = AiNodeGetFlt(node, "ray_min_dist"); + data->ray_max_dist = AiNodeGetFlt(node, "ray_max_dist"); + data->ray_max_depth = AiNodeGetInt(node, "ray_max_depth"); + data->trace_sets = AiNodeGetStr(node, "trace_sets"); + data->verbose = AiNodeGetBool(node, "verbose"); + if (data->sampler) + AiSamplerDestroy(data->sampler); + data->sampler = AiSampler(data->seed, data->ray_nsamples, data->ndim); +} + +shader_evaluate +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AtClosureList surface = AiShaderEvalParamClosure(p_surface); + if (!data->enable) + { + sg->out.CLOSURE() = surface; + return; + } + + if (sg->Rt & AI_RAY_SHADOW) + return; + + AtVector n = AiV3Normalize(sg->N); + AtVector tangent = sg->dPdu; + AtVector bitangent = sg->dPdv; + + SgCache sg_cache(sg); + string shading_object_name = AiNodeGetName(sg->Op); + AtRay ray; + AtVector rp = sg->P; + // AtVector n_sum = {0.f, 0.f, 0.f}; + + float samples[2]; + AtSamplerIterator *iterator = AiSamplerIterator(data->sampler, sg); + AtVector sample_N, sample_Nf, sample_Ns; + AtClosureList sample_shader; + float ray_length = AI_BIG; + + AiShaderGlobalsSetTraceSet(sg, data->trace_sets, false); + + int sample_count = AiSamplerGetSampleCount(iterator); + int nsmp = 0; + while (AiSamplerGetSample(iterator, samples)) + { + // float u, v; + // concentricSampleDisk(samples[0], samples[1], u, v); + // AtVector sample_dir = u * tangent + v * bitangent; + // sample_dir = AiV3Normalize(sample_dir); + AtVector sample_dir = AiV3Normalize(uniformSampleHemisphere(samples[0], samples[1])); + sample_dir += n; + sample_dir *= -1; + + ray = AiMakeRay(AI_RAY_ALL_DIFFUSE, rp, &sample_dir, data->ray_max_dist, sg); + float sample_length; + + AtShaderGlobals *sample_point = AiShaderGlobals(); + + if (!AiTraceProbe(ray, sample_point)) + { + AiShaderGlobalsDestroy(sample_point); + nsmp++; + continue; + } + + string sample_object_name = AiNodeGetName(sample_point->Op); + if (sample_object_name == shading_object_name) + { + AiShaderGlobalsDestroy(sample_point); + nsmp++; + continue; + } + + sample_length = AiV3Length(sample_point->P - sg->P); + if (data->verbose) + { + AiMsgDebug("## id : %d", nsmp); + AiMsgDebug("## rp : %f, %f, %f", rp.x, rp.y, rp.z); + AiMsgDebug("## dir : %f, %f, %f", sample_dir.x, sample_dir.y, sample_dir.z); + AiMsgDebug("## smp : %f, %f, %f", sample_point->P.x, sample_point->P.y, sample_point->P.z); + AiMsgDebug("## len : %f", sample_length); + } + if (sample_length < ray_length) + { + ray_length = min(ray_length, sample_length); + + sample_shader = sample_point->out.CLOSURE(); + sample_N = sample_point->N; + sample_Nf = sample_point->Nf; + sample_Ns = sample_point->Ns; + nsmp++; + } + } + + AiShaderGlobalsUnsetTraceSet(sg); + + if (ray_length > data->ray_max_length) + { + sg->out.CLOSURE() = AiShaderEvalParamClosure(p_surface); + return; + } + + float rv = ray_length / data->ray_max_length; + + // Interploate normal + sg->N = ((1.0 - rv) * sample_N) + (rv * sg->N); + sg->Nf = ((1.0 - rv) * sample_Nf) + (rv * sg->Nf); + sg->Ns = ((1.0 - rv) * sample_Ns) + (rv * sg->Ns); + + // Interpolate shading + // surface.add(AiClosureTransparent(sg, AtRGB(rv))); + // sample_shader.add(AiClosureTransparent(sg, AI_RGB_WHITE - AtRGB(rv))); + + AtClosureList result; + if (rv < 1) + { + if (data->verbose) + AiMsgInfo("rv : %f", rv); + // result.add(sample_shader); + // sample_shader.add(AiClosureTransparent(sg, AI_RGB_WHITE - AtRGB(0.5))); + sg->out.CLOSURE() = AiClosureEmission(sg, AI_RGB_RED); + // return; + } + else + { + sg->out.CLOSURE() = AiClosureEmission(sg, AI_RGB_GREEN); + + // sg->out.CLOSURE() = surface; + } + // result.add(surface); + // result.add(sample_shader); + // sg->out.CLOSURE() = result; + + sg_cache.restore(); +} + +node_loader +{ + if (i > 0) + return false; + + node->methods = apCrossBlend; + node->output_type = AI_TYPE_CLOSURE; + node->name = "apCrossBlend"; + node->node_type = AI_NODE_SHADER; + strcpy(node->version, AI_VERSION); + return true; +} diff --git a/src/apCrossBlend/apCrossBlend.mtd b/src/apCrossBlend/apCrossBlend.mtd new file mode 100644 index 0000000..0a6202e --- /dev/null +++ b/src/apCrossBlend/apCrossBlend.mtd @@ -0,0 +1,48 @@ +[node apCrossBlend] + maya.name STRING "apCrossBlend" + maya.id INT 0x0005119 + maya.classification STRING "shader/surface" + [attr surface] + desc STRING "Input Surface" + maya.keyable BOOL false + linkable BOOL true + + [attr enable] + desc STRING "Enable" + maya.keyable BOOL false + linkable BOOL false + + [attr ray_max_length] + desc STRING "Blend Length" + maya.keyable BOOL false + linkable BOOL false + + [attr ray_nsamples] + desc STRING "Num of Closest Point Samples" + maya.keyable BOOL false + maya.linkable BOOL false + + [attr ray_min_dist] + desc STRING "Ray Sample Min Dist" + maya.keyable BOOL false + maya.linkable BOOL false + + [attr ray_max_dist] + desc STRING "Ray Sample Max Dist" + maya.keyable BOOL false + maya.linkable BOOL false + + [attr ray_max_depth] + desc STRING "Ray Sample Max Dist" + maya.keyable BOOL false + maya.linkable BOOL false + + [attr trace_sets] + desc STRING "Sample Trace Sets" + maya.keyable BOOL false + maya.linkable BOOL false + + [attr verbose] + desc STRING "Verbose" + maya.keyable BOOL false + maya.linkable BOOL false \ No newline at end of file diff --git a/src/apCrossBlend/apCrossBlendTemplate.py b/src/apCrossBlend/apCrossBlendTemplate.py new file mode 100644 index 0000000..35bb510 --- /dev/null +++ b/src/apCrossBlend/apCrossBlendTemplate.py @@ -0,0 +1,31 @@ +import maya.mel +from mtoa.ui.ae.shaderTemplate import ShaderAETemplate + + +class AEapCrossBlendTemplate(ShaderAETemplate): + def setup(self): + self.addSwatch() + self.beginScrollLayout() + self.beginLayout("Material", collapse=False) + self.addControl('enable', label='Enable', + annotation='Enable Shader') + self.addControl('surface', label='Input Surface', + annotation='Input Surface') + self.addControl('ray_max_length', label='Blend Length', + annotation='Blend Length') + self.addControl('ray_nsamples', label='Ray Samples', + annotation='Closest Point Sample Number') + self.addControl('ray_min_dist', label='Ray Min Dist', + annotation='Ray Min Dist') + self.addControl('ray_max_dist', label='Ray Max Dist', + annotation='Ray Max Dist') + self.addControl('ray_max_depth', label='Ray Max Depth', + annotation='Ray Max Depth') + self.addControl('trace_sets', label='Trace Sets', + annotation='Trace Sets for Search Closest Point') + self.addControl('verbose', label='Verbose', + annotation='Verbose') + self.endLayout() + maya.mel.eval('AEdependNodeTemplate '+self.nodeName) + self.addExtraControls() + self.endScrollLayout() diff --git a/src/apCurveSample/CMakeLists.txt b/src/apCurveSample/CMakeLists.txt new file mode 100644 index 0000000..5efd887 --- /dev/null +++ b/src/apCurveSample/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(extension) +add_subdirectory(shader) \ No newline at end of file diff --git a/src/apCurveSample/extension/CMakeLists.txt b/src/apCurveSample/extension/CMakeLists.txt new file mode 100644 index 0000000..9a9f7c7 --- /dev/null +++ b/src/apCurveSample/extension/CMakeLists.txt @@ -0,0 +1,36 @@ +project(apCurveDataTranslator) + +set(SRC_FILES + "CurveDataTranslator.h" + "CurveDataTranslator.cpp" + "define.h" + "PfxHair.h" + "PfxHair.cpp" + "Plugin.cpp" + "Xgen.h" + "Xgen.cpp" + "utils.h" + "utils.cpp") + + + +Find_Package(Maya) + +include_directories( + ${ARNOLD_INCLUDE_PATH} + ${MTOA_INCLUDE_PATH} + ${MAYA_INCLUDE_PATH} + ${MAYA_XGEN_INCLUDE_PATH} +) +add_library(${PROJECT_NAME} SHARED ${SRC_FILES}) +set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "") + +target_link_libraries(${PROJECT_NAME} + ${ARNOLD_AI_LIBRARY} + ${MTOA_API_LIBRARY} + ${MAYA_LIBRARIES} + ${MAYA_XGEN_LIBRARIES}) + +set(INSTALL_SHADER_TARGET "${CMAKE_INSTALL_PREFIX}/${ARNOLD_VERSION}/${CMAKE_PROJECT_NAME}/extensions") + +install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${INSTALL_SHADER_TARGET}) \ No newline at end of file diff --git a/src/apCurveSample/extension/CurveAPI.h b/src/apCurveSample/extension/CurveAPI.h new file mode 100644 index 0000000..68974a1 --- /dev/null +++ b/src/apCurveSample/extension/CurveAPI.h @@ -0,0 +1,70 @@ +#include "define.h" + +#include +#include + +namespace CurveAPI +{ + typedef StringArray MeshArray; + class CurveBaseAPI + { + public: + CurveBaseAPI(); + virtual ~CurveBaseAPI() = 0; + virtual MObjectArray GetMeshFromIndex(int index) = 0; + virtual IntArray GetIndexesFromMesh(MObject &mesh) = 0; + virtual MObjectArray GetBaseMesh() = 0; + virtual MStatus GetRootPoints(MPointArray &) = 0; + virtual MStatus GetRootNormals(MVectorArray &) = 0; + virtual int GetSegment(); + virtual int Count(); + MObject &GetNode() { return m_node; }; + MDagPath &GetDagPath(); + void Set(MObject &node) { m_node = node; }; + bool IsRenderable(); + + private: + MObject m_node; + }; + + class HairCurveAPI : public CurveBaseAPI + { + public: + HairCurveAPI(MObject &pfxNode); + HairCurveAPI(MString name); + ~HairCurveAPI(); + MObjectArray GetMeshFromIndex(int index) override; + MStatus GetRootPoints(MPointArray &rootPoints) override; + MStatus GetRootNormals(MVectorArray &rootNormals) override; + MObject GetHairSystem(); + + private: + MObject m_node; + }; + + class XGenIGSCurveAPI : public CurveBaseAPI + { + public: + XGenIGSCurveAPI(MObject &node); + XGenIGSCurveAPI(MString name); + ~XGenIGSCurveAPI(); + + MStatus GetRootPoints(MPointArray &rootPoints) override; + MStatus GetRootNormals(MVectorArray &rootNormals) override; + + private: + MObject m_node; + }; + + class YetiCurveAPI : public CurveBaseAPI + { + public: + YetiCurveAPI(MObject &node); + YetiCurveAPI(MString name); + ~YetiCurveAPI(); + MStatus GetRootPoints(MPointArray &rootPoints) override; + + private: + MObject m_node; + }; +} diff --git a/src/apCurveSample/extension/CurveDataTranslator.cpp b/src/apCurveSample/extension/CurveDataTranslator.cpp new file mode 100644 index 0000000..a008bfd --- /dev/null +++ b/src/apCurveSample/extension/CurveDataTranslator.cpp @@ -0,0 +1,323 @@ +#include "CurveDataTranslator.h" +#include "Xgen.h" +#include "PfxHair.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void CCurveDataTranslator::NodeInitializer(CAbTranslator context) +{ + AiMsgInfo("[%s] : NodeInitializer()", kTranslatorName); +} + +AtNode *CCurveDataTranslator::CreateArnoldNodes() +{ + AiMsgInfo("[%s] : CreateArnoldNodes()", kTranslatorName); + return AddArnoldNode("apCurveSample"); +} + +void CCurveDataTranslator::Delete() +{ +} + +void CCurveDataTranslator::Update(AtNode *shader) +{ +} + +void CCurveDataTranslator::Export(AtNode *shader) +{ + clock_t tic, toc; + tic = clock(); + MStatus status; + + AtNode *option = AiUniverseGetOptions(); + + AiMsgInfo("[%s] : Export()", kTranslatorName); + AiMsgInfo("[%s] : Starting translate %s", kTranslatorName, GetMayaNodeName().asChar()); + MFnDependencyNode fnDepNode(GetMayaObject()); + MPlug outColorPlug = fnDepNode.findPlug("outColor", true, &status); + + MPlugArray destPlugArray; + outColorPlug.destinations(destPlugArray, &status); + + MItDependencyNodes dgHairIt(MFn::kPfxHair); + + AiMsgInfo("[%s] : Looking pfxHair ...", kTranslatorName); + for (; !dgHairIt.isDone(); dgHairIt.next()) + { + + MObject currentNode = dgHairIt.thisNode(); + + PfxHairHelper pfxHairHelper(currentNode); + MFnDagNode fnPfxHairNode(currentNode); + AiMsgInfo("[%s] : Current Node : %s", kTranslatorName, fnPfxHairNode.fullPathName().asChar()); + + if (!pfxHairHelper.IsRenderable()) + continue; + + MIntArray hairSegments = pfxHairHelper.GetHairBaseSegement(); + + int cvCount = hairSegments[0]; + MString pfxHairPath = fnPfxHairNode.fullPathName(); + pfxHairPath.substitute("|", "/"); + + const MString cvCountParam = MString(pfxHairPath + "_cv_count"); + + if (!AiNodeLookUpUserParameter(option, cvCountParam.asChar())) + AiNodeDeclare(option, cvCountParam.asChar(), "constant INT"); + + AiNodeSetInt(option, AtString(cvCountParam.asChar()), cvCount); + AiMsgInfo("[%s] : Export params : %s", kTranslatorName, cvCountParam.asChar()); + + AiMsgInfo("-------------------------------------"); + AiMsgInfo("[%s] : pfxHair : %s", kTranslatorName, fnPfxHairNode.partialPathName().asChar()); + AiMsgInfo("-------------------------------------"); + + MObjectArray hairBaseMeshList = pfxHairHelper.GetHairBaseMesh(); + const MString meshParam = MString(pfxHairPath + "_meshs"); + + if (!AiNodeLookUpUserParameter(option, meshParam.asChar())) + AiNodeDeclare(option, meshParam.asChar(), "constant ARRAY STRING"); + + AtArray *meshArray = AiArrayAllocate(hairBaseMeshList.length(), 1, AI_TYPE_STRING); + for (unsigned int i = 0; i < hairBaseMeshList.length(); i++) + { + MFnDependencyNode meshNode(hairBaseMeshList[i]); + AiArraySetStr(meshArray, i, AtString(meshNode.name().asChar())); + } + AiNodeSetArray(option, meshParam.asChar(), meshArray); + + AiMsgInfo("[%s] : array string[%d] : %s", kTranslatorName, hairBaseMeshList.length(), meshParam.asChar()); + + MPointArray rootPoints; + MVectorArray rootNormals; + pfxHairHelper.GetHairRootPointsAndNormals(rootPoints, rootNormals); + + AiMsgInfo("[%s] : Export root points", kTranslatorName); + const MString rootPointParam = MString(pfxHairPath + "_points"); + + AiMsgInfo("[%s] : array vector[%d] : %s", kTranslatorName, rootPoints.length(), rootPointParam.asChar()); + + if (!AiNodeLookUpUserParameter(option, rootPointParam.asChar())) + AiNodeDeclare(option, rootPointParam.asChar(), "constant ARRAY VECTOR"); + + AtArray *pointArray = AiArrayAllocate(rootPoints.length(), 1, AI_TYPE_VECTOR); + + for (unsigned i = 0; i < rootPoints.length(); i++) + { + MPoint rp = rootPoints[i]; + AiArraySetVec(pointArray, i, AtVector(rp.x, rp.y, rp.z)); + } + + AiNodeSetArray(option, rootPointParam.asChar(), pointArray); + AiMsgInfo("-------------------------------------"); + + AiMsgInfo("[%s] : Export root normals", kTranslatorName); + + const MString rootNormalParam = MString(pfxHairPath + "_normals"); + + AiMsgInfo("[%s] : array vector[%d] : %s", kTranslatorName, rootNormals.length(), rootNormalParam.asChar()); + + if (!AiNodeLookUpUserParameter(option, rootNormalParam.asChar())) + AiNodeDeclare(option, rootNormalParam.asChar(), "constant ARRAY VECTOR"); + AtArray *normalArray = AiArrayAllocate(rootNormals.length(), 1, AI_TYPE_VECTOR); + + for (unsigned i = 0; i < rootNormals.length(); i++) + { + MVector rn = rootNormals[i]; + AiArraySetVec(normalArray, i, AtVector(rn.x, rn.y, rn.z)); + } + + AiNodeSetArray(option, rootNormalParam.asChar(), normalArray); + AiMsgInfo("-------------------------------------"); + } + + // Looking the shader assignment + MItDependencyGraph *dgIt; + dgIt = new MItDependencyGraph(outColorPlug, MFn::kShadingEngine, + MItDependencyGraph::kDownstream, + MItDependencyGraph::kBreadthFirst, + MItDependencyGraph::kNodeLevel, + &status); + for (; !dgIt->isDone(); dgIt->next()) + { + // Get shading group from current item + MObject dest = dgIt->currentItem(); + + if (!dest.hasFn(MFn::kShadingEngine)) + continue; + + MFnSet fnSG(dest); + MSelectionList setMember; + fnSG.getMembers(setMember, true); + // Look each assignment of the SG + for (unsigned j = 0; j < setMember.length(); j++) + { + MObject desc; + MDagPath descPath; + + setMember.getDependNode(j, desc); + setMember.getDagPath(j, descPath); + MFnDagNode fnDescNode(descPath); + + XGenHelper xgenHelper(desc); + + if (!descPath.isVisible()) + continue; + MString descPathName = fnDescNode.fullPathName(); + descPathName.substitute("|", "/"); + MString descParamBaseName = descPathName + "_curves"; + AiMsgInfo("[%s] : %s api_type=%s", kTranslatorName, fnDescNode.name().asChar(), desc.apiTypeStr()); + AiMsgInfo("[%s] : %s node_type=%s", kTranslatorName, fnDescNode.name().asChar(), fnDescNode.typeName().asChar()); + // XGen Interactive Groom Spline + // We only care about xgmSplineDescription + if (fnDescNode.typeName() == "xgmSplineDescription") + { + // Set Export RenderStats + fnDescNode.findPlug("castsShadows").setValue(0); + fnDescNode.findPlug("receiveShadows").setValue(0); + fnDescNode.findPlug("aiVisibleInDiffuseReflection").setValue(0); + fnDescNode.findPlug("aiVisibleInSpecularReflection").setValue(0); + + static const MString sApplyRenderOverrideCmd = "xgmSplineApplyRenderOverride "; + MGlobal::executeCommand(sApplyRenderOverrideCmd + fnDescNode.partialPathName()); + + MObject splineBase = xgenHelper.GetSplineBase(); + // GetSplineBaseNode(descObject, splineBase); + + MFnDependencyNode fnSplineBase(splineBase); + // int cvCount = GetSplineBaseSegement(splineBase); + int cvCount = xgenHelper.GetBaseSegment(); + + const MString cvCountParam = descParamBaseName + "_cv_count"; + if (!AiNodeLookUpUserParameter(option, cvCountParam.asChar())) + AiNodeDeclare(option, cvCountParam.asChar(), "constant INT"); + AiNodeSetInt(option, AtString(cvCountParam.asChar()), cvCount); + + // MSelectionList meshList = GetSplineBaseMesh(splineBase); + MObjectArray meshList = xgenHelper.GetSplineBaseMesh(); + + AiMsgInfo("-------------------------------------"); + AiMsgInfo("[%s] : xgmSplineDescription : %s", kTranslatorName, fnDescNode.partialPathName().asChar()); + AiMsgInfo("[%s] : xgmSplineBase : %s", kTranslatorName, fnSplineBase.name().asChar()); + AiMsgInfo("-------------------------------------"); + + const MString meshParam = descParamBaseName + "_meshs"; + + if (!AiNodeLookUpUserParameter(option, meshParam.asChar())) + AiNodeDeclare(option, meshParam.asChar(), "constant ARRAY STRING"); + + AtArray *meshArray = AiArrayAllocate(meshList.length(), 1, AI_TYPE_STRING); + for (unsigned int i = 0; i < meshList.length(); i++) + { + MObject meshObj = meshList[i]; + MFnDagNode meshNode(meshObj); + MString meshPath = meshNode.fullPathName(); + meshPath.substitute("|", "/"); + AiArraySetStr(meshArray, i, AtString(meshPath.asChar())); + } + + AiNodeSetArray(option, meshParam.asChar(), meshArray); + + MPointArray rootPoints; + MVectorArray rootNormals; + + // GetSplineRootPointsAndNormals(fnDescNode.partialPathName().asChar(), rootPoints, rootNormals); + xgenHelper.GetSplineRootPointsAndNormals(rootPoints, rootNormals); + + // getSplineRootPoints(fnDescNode.partialPathName().asChar(), rootPoints); + + AiMsgInfo("[%s] : Export root points", kTranslatorName); + const MString rootPointParam = descParamBaseName + "_points"; + + AiMsgInfo("[%s] : array vector[%d] : %s", kTranslatorName, rootPoints.length(), rootPointParam.asChar()); + + if (!AiNodeLookUpUserParameter(option, rootPointParam.asChar())) + AiNodeDeclare(option, rootPointParam.asChar(), "constant ARRAY VECTOR"); + + AtArray *pointArray = AiArrayAllocate(rootPoints.length(), 1, AI_TYPE_VECTOR); + + for (unsigned i = 0; i < rootPoints.length(); i++) + { + MPoint rp = rootPoints[i]; + AiArraySetVec(pointArray, i, AtVector(rp.x, rp.y, rp.z)); + } + + AiNodeSetArray(option, rootPointParam.asChar(), pointArray); + + AiMsgInfo("-------------------------------------"); + + // getSplineRootNormals(fnDescNode.partialPathName().asChar(), rootNormals); + AiMsgInfo("[%s] : Export root normals", kTranslatorName); + + const MString rootNormalParam = descParamBaseName + "_normals"; + + AiMsgInfo("[%s] : array vector[%d] : %s", kTranslatorName, rootNormals.length(), rootNormalParam.asChar()); + + if (!AiNodeLookUpUserParameter(option, rootNormalParam.asChar())) + AiNodeDeclare(option, rootNormalParam.asChar(), "constant ARRAY VECTOR"); + AtArray *normalArray = AiArrayAllocate(rootNormals.length(), 1, AI_TYPE_VECTOR); + + for (unsigned i = 0; i < rootNormals.length(); i++) + { + MVector rn = rootNormals[i]; + AiArraySetVec(normalArray, i, AtVector(rn.x, rn.y, rn.z)); + } + + AiNodeSetArray(option, rootNormalParam.asChar(), normalArray); + AiMsgInfo("-------------------------------------"); + } + } + } + + AiMsgInfo("[%s] : Exporting %s settings", kTranslatorName, GetMayaNodeName().asChar()); + ProcessParameter(shader, "sample_data_type", AI_TYPE_INT, "sampleDataType"); + ProcessParameter(shader, "normalize", AI_TYPE_BOOLEAN, "normalize"); + ProcessParameter(shader, "trace_set", AI_TYPE_STRING, "traceSet"); + ProcessParameter(shader, "ray_offset", AI_TYPE_FLOAT, "rayOffset"); + ProcessParameter(shader, "ray_max_depth", AI_TYPE_INT, "rayMaxDepth"); + ProcessParameter(shader, "ray_max_sample", AI_TYPE_INT, "rayMaxSample"); + ProcessParameter(shader, "occ_min_dist", AI_TYPE_FLOAT, "occMinDist"); + ProcessParameter(shader, "occ_max_dist", AI_TYPE_FLOAT, "occMaxDist"); + ProcessParameter(shader, "occ_spread", AI_TYPE_FLOAT, "occSpread"); + ProcessParameter(shader, "occ_falloff", AI_TYPE_FLOAT, "occFalloff"); + ProcessParameter(shader, "error_color", AI_TYPE_RGB, "errorColor"); + ProcessParameter(shader, "verbose", AI_TYPE_BOOLEAN, "verbose"); + + // Export parameter to shader tree or value + /* + ProcessParameter(shader, "root_color_gain", AI_TYPE_RGB, "rootColorGain"); + ProcessParameter(shader, "root_color_offset", AI_TYPE_RGB, "rootColorOffset"); + ProcessParameter(shader, "tip_color_gain", AI_TYPE_RGB, "tipColorGain"); + ProcessParameter(shader, "tip_color_offset", AI_TYPE_RGB, "tipColorOffset"); + ProcessParameter(shader, "ray_offset", AI_TYPE_FLOAT, "rayOffset"); + ProcessParameter(shader, "ray_max_depth", AI_TYPE_INT, "rayMaxDepth"); + ProcessParameter(shader, "ray_max_sample", AI_TYPE_INT, "rayMaxSample"); + ProcessParameter(shader, "trace_set", AI_TYPE_STRING, "traceSet"); + ProcessParameter(shader, "verbose", AI_TYPE_BOOLEAN, "verbose"); + ProcessParameter(shader, "debug", AI_TYPE_BOOLEAN, "debug"); + */ + + toc = clock(); + + AiMsgInfo("[%s] : Export in %lf sec", kTranslatorName, (toc - tic) / (double)CLOCKS_PER_SEC); + AiMsgInfo("[%s] : Export finish : %s", kTranslatorName, fnDepNode.name().asChar()); +} \ No newline at end of file diff --git a/src/apCurveSample/extension/CurveDataTranslator.h b/src/apCurveSample/extension/CurveDataTranslator.h new file mode 100644 index 0000000..2f22028 --- /dev/null +++ b/src/apCurveSample/extension/CurveDataTranslator.h @@ -0,0 +1,28 @@ +#pragma once + +//#include +//#include +#include +#include + +#include "define.h" + +using namespace std; + +class CCurveDataTranslator : public CShaderTranslator +{ +public: + AtNode *CreateArnoldNodes(); + virtual void Export(AtNode *shader); + virtual void Update(AtNode *shader); + static void *creator() + { + AiMsgInfo(" [%s] :: initialized.", kTranslatorName); + AiMsgInfo("-----------------------------------------------------------------------------------"); + AiMsgInfo(" [%s] : Compile at %s : %s", kTranslatorName, __DATE__, __TIME__); + AiMsgInfo("-----------------------------------------------------------------------------------"); + return new CCurveDataTranslator(); + } + static void NodeInitializer(CAbTranslator context); + virtual void Delete(); +}; \ No newline at end of file diff --git a/src/apCurveSample/extension/PfxHair.cpp b/src/apCurveSample/extension/PfxHair.cpp new file mode 100644 index 0000000..66ab5f3 --- /dev/null +++ b/src/apCurveSample/extension/PfxHair.cpp @@ -0,0 +1,249 @@ +#include "PfxHair.h" +#include "utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +PfxHairHelper::PfxHairHelper(){}; + +PfxHairHelper::PfxHairHelper(MObject &pfxHair) + : m_pfxHair(pfxHair) +{ + m_hairSystem = GetHairSystem(); +} + +PfxHairHelper::PfxHairHelper(string pfxHair) +{ + GetMayaObject(pfxHair, m_pfxHair); + m_hairSystem = GetHairSystem(); +} + +PfxHairHelper::~PfxHairHelper(){}; + +MObject PfxHairHelper::GetHairSystem() +{ + MObject hairSystem; + MFnPfxGeometry fnPfxHair(m_pfxHair); + MObjectArray hairSystems = GetTypeNodes(fnPfxHair.findPlug("renderHairs"), + MItDependencyGraph::kUpstream, + MFn::kHairSystem); + if (hairSystems.length()) + hairSystem = hairSystems[0]; + return hairSystem; +} + +MRenderLineArray PfxHairHelper::GetHairData(MStatus *status) +{ + MFnPfxGeometry fnPfxNode(m_pfxHair); + AiMsgInfo("[%s] : PfxNode : %s", kTranslatorName, fnPfxNode.fullPathName().asChar()); + MDagPath pfxPath = fnPfxNode.dagPath(); + MRenderLineArray renderLineArray, leafLines, flowerLines; + fnPfxNode.getLineData(renderLineArray, leafLines, flowerLines, true, false, false, false, false, false, false, false, true); + return renderLineArray; +} + +int PfxHairHelper::GetHairCount() +{ + MStatus status; + MRenderLineArray renderLineArray = GetHairData(&status); + if (status == MS::kFailure) + return 0; + return renderLineArray.length(); +} + +MIntArray PfxHairHelper::GetHairBaseSegement(MStatus *status) +{ + MIntArray segmentArray; + MRenderLineArray renderLineArray = GetHairData(); + for (int i = 0; i < renderLineArray.length(); i++) + { + segmentArray.append(renderLineArray.renderLine(i, status).getLine().length()); + } + return segmentArray; +} + +MObjectArray PfxHairHelper::GetHairBaseMesh() +{ + return GetTypeNodes(m_hairSystem, MItDependencyGraph::kUpstream, MFn::kMesh); +} + +IndexArrayMap PfxHairHelper::GetMeshHairIndexMap() +{ + MStatus status; + IndexArrayMap meshHairIndexMap; + MFnDependencyNode fnHairSystem(m_hairSystem); + MPlug inputHairPlug = fnHairSystem.findPlug("inputHair"); + // AiMsgInfo("[%s] : inputHair array count : %d", kTranslatorName, inputHairPlug.numElements()); + for (unsigned int i = 0; i < inputHairPlug.numElements(); i++) + { + MPlug inputHairIndexPlug = inputHairPlug.connectionByPhysicalIndex(i, &status); + MPlug folliclePlug = inputHairIndexPlug.source(&status); + if (folliclePlug.isNull() || status == MS::kFailure) + continue; + MFnDependencyNode fnFollicleNode(folliclePlug.node()); + MPlug inMeshPlug = fnFollicleNode.findPlug("inputMesh"); + MPlug meshPlug = inMeshPlug.source(&status); + // AiMsgInfo("[%s] : inputMesh plug : %s", kTranslatorName , meshPlug.name().asChar()); + if (meshPlug.isNull() || status == MS::kFailure) + continue; + MObject meshObject = meshPlug.node(); + MFnMesh fnMesh(meshObject); + string meshPath = fnMesh.fullPathName().asChar(); + // AiMsgInfo("[%s] : inputMesh : %s", kTranslatorName, meshPath.c_str()); + if (meshHairIndexMap.find(meshPath) == meshHairIndexMap.end()) + meshHairIndexMap[meshPath] = MIntArray(); + meshHairIndexMap[meshPath].append(i); + } + return meshHairIndexMap; +} + +MStatus PfxHairHelper::GetMeshFromHairIndex(int hairIndex, MObject &hairMesh) +{ + IndexArrayMap meshHairIndexMap = GetMeshHairIndexMap(); + if (meshHairIndexMap.empty()) + return MS::kNotFound; + // for (const auto &[mesh, indexes] : meshHairIndexMap) + // for (auto indexMap : meshHairIndexMap) + for (auto it = meshHairIndexMap.begin(); it != meshHairIndexMap.end(); ++it) + { + string mesh = it->first; + MIntArray indexes = it->second; + for (unsigned int i = 0; i < indexes.length(); i++) + { + if (hairIndex != indexes[i]) + continue; + MSelectionList s_list; + s_list.clear(); + s_list.add(mesh.c_str()); + MObject meshObject; + s_list.getDependNode(0, meshObject); + hairMesh = meshObject; + return MS::kSuccess; + } + } + return MS::kNotFound; +} + +MStatus PfxHairHelper::GetMeshFromHairIndex(int hairIndex, MString &hairMesh) +{ + MObject meshObject; + GetMeshFromHairIndex(hairIndex, meshObject); + if (meshObject.isNull()) + return MS::kNotFound; + hairMesh = MFnDagNode(meshObject).fullPathName(); + return MS::kSuccess; +} + +void PfxHairHelper::GetHairRootPoints(PointArrayMap &rootPointArrayMap) +{ + MStatus status; + + MRenderLineArray renderLineArray = GetHairData(); + int renderLineCount = renderLineArray.length(); + int hairPerClump = GetHairsPerClump(); + AiMsgInfo("[%s] : Hair Render Line Count : %d", kTranslatorName, renderLineCount); + AiMsgInfo("[%s] : Hair Per Clump : %d", kTranslatorName, hairPerClump); + for (auto i = 0; i < renderLineArray.length(); i++) + { + int hairIndex = i / hairPerClump; + MRenderLine renderLine = renderLineArray.renderLine(i, &status); + MPoint rootPoint(renderLine.getLine()[0]); + MString hairMesh; + if (GetMeshFromHairIndex(hairIndex, hairMesh) == MS::kNotFound) + continue; + AiMsgInfo("[%s] : Hair Mesh Index : [%d] : %s", kTranslatorName, hairIndex, hairMesh.asChar()); + rootPointArrayMap[hairMesh.asChar()].append(rootPoint); + } +} + +void PfxHairHelper::GetHairRootPointsAndNormals(MPointArray &pointArray, MVectorArray &vectorArray, bool debug) +{ + MStatus status; + PointArrayMap rootPointArrayMap; + GetHairRootPoints(rootPointArrayMap); + // for (auto rp : rootPointArrayMap) + for (auto it = rootPointArrayMap.begin(); it != rootPointArrayMap.end(); ++it) + { + string mesh = it->first; + MPointArray rootPoints = it->second; + + MDagPath dagPath; + GetMayaDagPath(mesh, dagPath); + + if (!dagPath.isValid() || !dagPath.hasFn(MFn::kMesh)) + { + MGlobal::displayError(MString(mesh.c_str()) + " is invalid"); + continue; + } + + MMeshIntersector intersector; + MMatrix matrix = dagPath.inclusiveMatrix(); + status = intersector.create(dagPath.node(), matrix); + for (unsigned i = 0; i < rootPoints.length(); i++) + { + MPoint pt = rootPoints[i]; + MPointOnMesh pointInfo; + intersector.getClosestPoint(pt, pointInfo); + MFloatVector closestNormal = pointInfo.getNormal(); + closestNormal = closestNormal * -1; + pointArray.append(pt); + vectorArray.append(closestNormal); + } + } +} + +int PfxHairHelper::GetHairIndexFromCurveId(int curveId, MStatus *status = nullptr) +{ + int hairPerClump = GetHairsPerClump(); + int hairCount = GetHairCount(); + if (curveId > hairCount) + { + // std::cerr << "[Error] : curveId (" << curveId << ") is large the hair count( " + // << hairCount << ")" << endl; + return 0; + } + return curveId / hairPerClump; +} + +bool PfxHairHelper::IsRenderable() +{ + MFnDagNode fnPfxHair(m_pfxHair); + MDagPath pfxHairPath; + GetMayaDagPath(fnPfxHair.fullPathName().asChar(), pfxHairPath); + + if (pfxHairPath.isVisible()) + { + MFnDagNode fnHairSystem(m_hairSystem); + MPlug shaderPlug = fnHairSystem.findPlug("aiHairShader"); + MObjectArray shaderNodes = GetTypeNodes(shaderPlug, MItDependencyGraph::kUpstream); + MString sampleShaderType("apCurveSample"); + for (unsigned int i = 0; i < shaderNodes.length(); i++) + { + MFnDependencyNode fnNode(shaderNodes[i]); + AiMsgDebug("[%s] : shader : %s", kTranslatorName, fnNode.typeName().asChar()); + if (fnNode.typeName() == sampleShaderType) + { + AiMsgDebug("[%s] : Found %s : %s", kTranslatorName, sampleShaderType.asChar(), fnNode.typeName().asChar()); + return true; + } + } + } + return false; +} + +int PfxHairHelper::GetHairsPerClump() +{ + MFnDependencyNode fnHairNode(m_hairSystem); + MPlug hpcPlug = fnHairNode.findPlug("hairsPerClump"); + return hpcPlug.asInt(); +} \ No newline at end of file diff --git a/src/apCurveSample/extension/PfxHair.h b/src/apCurveSample/extension/PfxHair.h new file mode 100644 index 0000000..e9e447d --- /dev/null +++ b/src/apCurveSample/extension/PfxHair.h @@ -0,0 +1,42 @@ +#include "define.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class PfxHairHelper +{ +public: + PfxHairHelper(); + PfxHairHelper(MObject &pfxHair); + PfxHairHelper(string pfxHair); + ~PfxHairHelper(); + MObject GetPfxHairNode() { return m_pfxHair; }; + MObjectArray GetHairBaseMesh(); + IndexArrayMap GetMeshHairIndexMap(); + MStatus GetMeshFromHairIndex(int hairIndex, MObject &hairMesh); + MStatus GetMeshFromHairIndex(int hairIndex, MString &hairmesh); + MStatus GetHairIndexesFromMesh(MIntArray &indexes, MObject &mesh); + MRenderLineArray GetHairData(MStatus *status = nullptr); + void GetHairRootPoints(PointArrayMap &rootPointArrayMap); + void GetHairRootPointsAndNormals(MPointArray &pointArray, MVectorArray &vectorArray, bool debug = false); + MIntArray GetHairBaseSegement(MStatus *status = nullptr); + int GetHairCount(); + int GetHairIndexFromCurveId(int curveId, MStatus *status); + void GetHairLinesFromMesh(MObject &hairMesh, VectorArrayMap &hairArrayMap); + int GetHairsPerClump(); + bool IsRenderable(); + MObject &Get() { return m_pfxHair; }; + MObject GetHairSystem(); + +private: + MObject m_pfxHair; + MObject m_hairSystem; + MObjectArray m_pfxHairs; +}; diff --git a/src/apCurveSample/extension/Plugin.cpp b/src/apCurveSample/extension/Plugin.cpp new file mode 100644 index 0000000..099afc7 --- /dev/null +++ b/src/apCurveSample/extension/Plugin.cpp @@ -0,0 +1,16 @@ +#include "extension/Extension.h" + +#include "CurveDataTranslator.h" + +extern "C" +{ + DLLEXPORT void initializeExtension(CExtension &extension) + { + MStatus status; + extension.Requires("xgenToolkit"); + extension.RegisterTranslator("apCurveSample", + "", + CCurveDataTranslator::creator, + CCurveDataTranslator::NodeInitializer); + } +} \ No newline at end of file diff --git a/src/apCurveSample/extension/Xgen.cpp b/src/apCurveSample/extension/Xgen.cpp new file mode 100644 index 0000000..cf2916c --- /dev/null +++ b/src/apCurveSample/extension/Xgen.cpp @@ -0,0 +1,909 @@ +#include "Xgen.h" + +#include "utils.h" + +#include + +XGenHelper::XGenHelper(MObject &desc) + : m_description(desc) +{ + // GetSplineBase(m_splineBase); +} + +XGenHelper::XGenHelper(string descName) +{ + GetMayaObject(descName, m_description); + GetMayaDagPath(descName, m_descPath); + // GetSplineBase(m_splineBase); +} + +XGenHelper::XGenHelper(MDagPath &path) + : m_description(path.node()), m_descPath(path) +{ + // GetSplineBase(m_splineBase); +} + +XGenHelper::~XGenHelper() +{ +} + +void XGenHelper::GetSplineData(SplineDataMap &splineDataMap, unsigned int step) +{ + MFnDagNode fnDesc(m_description); + static const MString sApplyRenderOverrideCmd = "xgmSplineApplyRenderOverride "; + MGlobal::executeCommand(sApplyRenderOverrideCmd + fnDesc.partialPathName()); + + MObject splineBase = GetSplineBase(); + MFnDependencyNode fnSplineBase(splineBase); + + AiMsgDebug("-------------------------------------"); + AiMsgDebug("[%s] : xgmSplineDescription : %s", kTranslatorName, fnDesc.partialPathName().asChar()); + AiMsgDebug("[%s] : xgmSplineBase : %s", kTranslatorName, fnSplineBase.name().asChar()); + AiMsgDebug("-------------------------------------"); + + AiMsgInfo("[%s] : Init splineDataMap...", kTranslatorName); + MPlug boundMeshPlug = fnSplineBase.findPlug("boundMesh", true); + + for (unsigned int b = 0; b < boundMeshPlug.numElements(); b++) + { + MPlug p = boundMeshPlug.elementByLogicalIndex(b); + MPlug meshPlug = p.source(); + if (meshPlug.isNull()) + continue; + MFnMesh fnMesh(meshPlug.node()); + string meshName = fnMesh.name().asChar(); + SplineData splineData; + splineDataMap[meshName] = splineData; + + AiMsgInfo("[%s] : splineDataMap : %s", kTranslatorName, meshName.c_str()); + } + AiMsgInfo("-------------------------------------"); + + std::string data; + MPlug outPlug = fnDesc.findPlug("outRenderData"); + MObject outObj = outPlug.asMObject(); + MPxData *outData = MFnPluginData(outObj).data(); + + if (outData) + { + std::ostringstream opaqueStrm; + outData->writeBinary(opaqueStrm); + data = opaqueStrm.str(); + } + + // Compute the padding bytes and number of array elements + const unsigned int tail = data.size() % sizeof(unsigned int); + const unsigned int padding = (tail > 0) ? sizeof(unsigned int) - tail : 0; + const unsigned int nelements = (unsigned int)data.size() / sizeof(unsigned int) + (tail > 0 ? 1 : 0); + + const size_t sampleSize = size_t(nelements) * sizeof(unsigned int) - padding; + + AiMsgDebug(" tail : %s", tail); + AiMsgDebug(" padding : %s", padding); + AiMsgDebug(" nelements : %s", nelements); + AiMsgDebug(" sampleSize : %s", sampleSize); + + XgFnSpline splines; + + double frame; + MString cmd("currentTime -query"); + MGlobal::executeCommand(cmd, frame); + + // std::stringstream opaqueStrm; + // opaqueStrm.write(data.c_str(), sampleSize); + if (!splines.load(std::stringstream(data), sampleSize, (float)frame)) + { + AiMsgWarning("[%s] Failed to load sample.", kTranslatorName); + } + + // Process multiplier and density mask + splines.executeScript(); + + for (XgItSpline splineIt = splines.iterator(); !splineIt.isDone(); splineIt.next()) + { + const unsigned int stride = splineIt.primitiveInfoStride(); + const unsigned int primitiveCount = splineIt.primitiveCount(); + const unsigned int *primitiveInfos = splineIt.primitiveInfos(); + const SgVec3f *positions = splineIt.positions(0); +#if defined(XGEN_SPLINE_API_VERSION) && XGEN_SPLINE_API_VERSION >= XGEN_SPLINE_VERSION_2017_UPDATE3 + const SgVec3f *directions = splineIt.widthDirection(0); +#endif + AiMsgDebug(" stride : %d, primitiveCount : %d, meshId : %s", stride, primitiveCount, splineIt.boundMeshId()); + + string meshId = splineIt.boundMeshId(); + MPlug boundMeshPlug = fnSplineBase.findPlug("boundMesh", true); + + if (boundMeshPlug.numElements() == 0) + AiMsgWarning("[%s] : xgmSplineBase : No mesh connect to the %s.boundMesh.", kTranslatorName, fnSplineBase.name().asChar()); + + for (unsigned int b = 0; b < boundMeshPlug.numElements(); b++) + { + MPlug p = boundMeshPlug.elementByLogicalIndex(b); + int at = p.name().indexW(meshId.c_str()); + + if (at < 0) + continue; + + boundMeshPlug = p; + } + + if (boundMeshPlug.isNull()) + { + AiMsgWarning("[%s] : %s.boundMesh plug is Null.", kTranslatorName, fnSplineBase.name().asChar()); + continue; + } + + MPlug meshPlug = boundMeshPlug.source(); + MFnMesh fnMesh(meshPlug.node()); + string meshName = fnMesh.name().asChar(); + + AiMsgDebug(" boundMeshPlug : %s", boundMeshPlug.name().asChar()); + + for (unsigned int p = 0; p < primitiveCount; p++) + { + const unsigned int offset = primitiveInfos[p * stride]; + const unsigned int length = primitiveInfos[p * stride + 1]; + + AiMsgDebug(" offset : %d", offset); + AiMsgDebug(" length : %d", length); + + MPointArray curve_pts; + + for (unsigned int i = 0; i < length; i++) + { + SgVec3f p = positions[i + offset]; + MPoint cpt(p[0], p[1], p[2]); + curve_pts.append(cpt); + } + splineDataMap[meshName].push_back(curve_pts); + } + } + + AiMsgInfo("-------------------------------------"); + + for (auto it = splineDataMap.begin(); it != splineDataMap.end(); it++) + AiMsgInfo(" Mesh : %s, Spline Count : %d", it->first.c_str(), it->second.size()); + + AiMsgInfo("-------------------------------------"); +} + +void XGenHelper::GetSplineRootPoints(PointArrayMap &pointArrayMap, unsigned int step) +{ + AiMsgInfo("[%s] : GetSplineRootPoints() : %s", kTranslatorName, GetDescName().asChar()); + + SplineDataMap splineDataMap; + GetSplineData(splineDataMap, step); + for (auto it = splineDataMap.begin(); it != splineDataMap.end(); it++) + { + MPointArray points; + string mesh = it->first; + SplineData splineData = it->second; + + for (unsigned int i = 0; i < splineData.size(); i++) + { + MPointArray curve_pts = splineData[i]; + points.append(curve_pts[0]); + } + pointArrayMap[mesh] = points; + } +} + +void XGenHelper::GetSplineRootNormals(VectorArrayMap &normalArrayMap, unsigned int step) +{ + MStatus status; + PointArrayMap rootPointArrayMap; + GetSplineRootPoints(rootPointArrayMap, step); + + for (auto it = rootPointArrayMap.begin(); it != rootPointArrayMap.end(); it++) + { + MVectorArray normals; + + string mesh = it->first; + MPointArray rootPoints = it->second; + + MDagPath meshDagPath; + GetMayaDagPath(mesh, meshDagPath); + + if (!meshDagPath.isValid()) + { + MGlobal::displayError(GetDescName() + " is invalid"); + continue; + } + if (!meshDagPath.hasFn(MFn::kMesh)) + { + MGlobal::displayError(MString(mesh.c_str()) + " is invalid"); + continue; + } + + MMeshIntersector intersector; + MMatrix matrix = meshDagPath.inclusiveMatrix(); + status = intersector.create(meshDagPath.node(), matrix); + + if (status == MS::kFailure) + { + AiMsgError("Fail to create mesh intersector."); + return; + } + + if (status == MS::kInvalidParameter) + { + AiMsgError("Object is not a kMesh or kMeshData"); + return; + } + + for (unsigned i = 0; i < rootPoints.length(); i++) + { + MPoint pt = rootPoints[i]; + MPointOnMesh pointInfo; + intersector.getClosestPoint(pt, pointInfo); + MFloatVector closestNormal = pointInfo.getNormal(); + closestNormal = closestNormal * -1; + normals.append(closestNormal); + } + normalArrayMap[mesh] = normals; + } +} + +void XGenHelper::GetSplineRootPointsAndNormals(MPointArray &pointArray, MVectorArray &vectorArray, unsigned int step) +{ + AiMsgInfo("[%s] : getSplineRootPointsAndNormals() : %s", kTranslatorName, GetDescName().asChar()); + + MStatus status; + + PointArrayMap rootPointArrayMap; + GetSplineRootPoints(rootPointArrayMap, step); + + for (auto it = rootPointArrayMap.begin(); it != rootPointArrayMap.end(); it++) + { + string mesh = it->first; + MPointArray rootPoints = it->second; + + MDagPath meshDagPath; + GetMayaDagPath(mesh, meshDagPath); + + if (!meshDagPath.isValid()) + { + MGlobal::displayError(GetDescName() + " is invalid"); + continue; + } + if (!meshDagPath.hasFn(MFn::kMesh)) + { + MGlobal::displayError(MString(mesh.c_str()) + " is invalid"); + continue; + } + + MMeshIntersector intersector; + MMatrix matrix = meshDagPath.inclusiveMatrix(); + status = intersector.create(meshDagPath.node(), matrix); + + if (status == MS::kFailure) + { + AiMsgError("Fail to create mesh intersector."); + return; + } + + if (status == MS::kInvalidParameter) + { + AiMsgError("Object is not a kMesh or kMeshData"); + return; + } + for (unsigned i = 0; i < rootPoints.length(); i++) + { + MPoint pt = rootPoints[i]; + MPointOnMesh pointInfo; + intersector.getClosestPoint(pt, pointInfo); + MFloatVector closestNormal = pointInfo.getNormal(); + closestNormal = closestNormal * -1; + pointArray.append(pt); + vectorArray.append(closestNormal); + } + } +} + +MObjectArray XGenHelper::GetSplineBaseMesh() +{ + MObject splineBase = GetSplineBase(); + MObjectArray meshList; + MFnDependencyNode fnSplineBaseNode(splineBase); + MString name = fnSplineBaseNode.name(); + MPlug boundMeshPlug = fnSplineBaseNode.findPlug("boundMesh"); + for (unsigned int i = 0; i < boundMeshPlug.numElements(); i++) + { + MPlug p = boundMeshPlug.elementByLogicalIndex(i); + MPlug meshPlug = p.source(); + if (meshPlug.isNull()) + continue; + meshList.append(meshPlug.node()); + } + return meshList; +} + +MObject XGenHelper::GetSplineBase() +{ + MObject splineBase; + MFnDependencyNode fnDesc(m_description); + MPlug rootPlug = fnDesc.findPlug("inSplineData", true); + MObjectArray splineBaseNodes = GetTypeNodes(rootPlug, "xgmSplineBase", MItDependencyGraph::kUpstream); + if (splineBaseNodes.length()) + splineBase = splineBaseNodes[0]; + return splineBase; +} + +bool XGenHelper::HasBoundMesh() +{ + MObject splineBase = GetSplineBase(); + MFnDependencyNode fnSplineBase(splineBase); + MPlug boundMeshPlug = fnSplineBase.findPlug("boundMesh", true); + return (boundMeshPlug.numElements() > 0) ? true : false; +} + +MString XGenHelper::GetDescName(bool fullPathName) +{ + MFnDagNode fnDesc(m_description); + if (fullPathName) + return fnDesc.fullPathName(); + return fnDesc.name(); +} + +MString XGenHelper::GetSplineBaseName() +{ + MObject splineBase = GetSplineBase(); + MFnDependencyNode fnSplineBase(splineBase); + return fnSplineBase.name(); +} + +int XGenHelper::GetBaseSegment() +{ + MObject splineBase = GetSplineBase(); + MFnDependencyNode fnSplineBase(splineBase); + MPlug cvCountPlug = fnSplineBase.findPlug("cvCount"); + int cvCount = cvCountPlug.asInt(); + return cvCount; +} + +void GetSplineData(string description, SplineData &splineData, unsigned int step, bool debug) +{ + MSelectionList selList; + selList.clear(); + selList.add(MString(description.c_str())); + MDagPath descDagPath; + selList.getDagPath(0, descDagPath); + MObject descNode; + selList.getDependNode(0, descNode); + + if (!descDagPath.isValid()) + { + AiMsgWarning("[%s] : %s is invalid.", kTranslatorName, description.c_str()); + } + + MFnDagNode fnDagNode(descDagPath); + static const MString sApplyRenderOverrideCmd = "xgmSplineApplyRenderOverride "; + MGlobal::executeCommand(sApplyRenderOverrideCmd + fnDagNode.partialPathName()); + + MObject splineBase; + GetSplineBaseNode(descNode, splineBase); + + MFnDependencyNode fnSplineBaseNode(splineBase); + + AiMsgDebug("-------------------------------------"); + AiMsgDebug("[%s] : xgmSplineDescription : %s", kTranslatorName, fnDagNode.partialPathName().asChar()); + AiMsgDebug("[%s] : xgmSplineBase : %s", kTranslatorName, fnSplineBaseNode.name().asChar()); + AiMsgDebug("-------------------------------------"); + + // Init mesh spline data map + MPlug boundMeshPlug = fnSplineBaseNode.findPlug("boundMesh", true); + + if (boundMeshPlug.numElements() == 0) + AiMsgWarning("[%s] : xgmSplineBase : No mesh connect to the %s.boundMesh", kTranslatorName, fnSplineBaseNode.name().asChar()); + + std::string data; + MPlug outPlug = fnDagNode.findPlug("outRenderData"); + MObject outObj = outPlug.asMObject(); + MPxData *outData = MFnPluginData(outObj).data(); + + if (outData) + { + std::ostringstream opaqueStrm; + outData->writeBinary(opaqueStrm); + data = opaqueStrm.str(); + } + + // Compute the padding bytes and number of array elements + const unsigned int tail = data.size() % sizeof(unsigned int); + const unsigned int padding = (tail > 0) ? sizeof(unsigned int) - tail : 0; + const unsigned int nelements = (unsigned int)data.size() / sizeof(unsigned int) + (tail > 0 ? 1 : 0); + + const size_t sampleSize = size_t(nelements) * sizeof(unsigned int) - padding; + + AiMsgDebug(" tail : %s", tail); + AiMsgDebug(" padding : %s", padding); + AiMsgDebug(" nelements : %s", nelements); + AiMsgDebug(" sampleSize : %s", sampleSize); + + double frame; + MString cmd("currentTime -query"); + MGlobal::executeCommand(cmd, frame); + + XgFnSpline splines; + // std::stringstream opaqueStrm; + // opaqueStrm.write(data.c_str(), sampleSize); + if (!splines.load(std::stringstream(data), sampleSize, (float)frame)) + { + AiMsgWarning("[%s] : Failed to load sample.", kTranslatorName); + } + + splines.executeScript(); + + for (XgItSpline splineIt = splines.iterator(); !splineIt.isDone(); splineIt.next()) + { + const unsigned int stride = splineIt.primitiveInfoStride(); + const unsigned int primitiveCount = splineIt.primitiveCount(); + const unsigned int *primitiveInfos = splineIt.primitiveInfos(); + const SgVec3f *positions = splineIt.positions(0); +#if defined(XGEN_SPLINE_API_VERSION) && XGEN_SPLINE_API_VERSION >= XGEN_SPLINE_VERSION_2017_UPDATE3 + const SgVec3f *directions = splineIt.widthDirection(0); +#endif + AiMsgDebug(" stride : %d", stride); + + AiMsgInfo(" primitiveCount : %d, meshId : %s", primitiveCount, splineIt.boundMeshId()); + + string meshId = splineIt.boundMeshId(); + MPlug boundMeshPlug = fnSplineBaseNode.findPlug("boundMesh", true); + + if (boundMeshPlug.numElements() == 0) + AiMsgWarning("[%s] : xgmSplineBase : No mesh connect to the %s.boundMesh.", kTranslatorName, fnSplineBaseNode.name().asChar()); + + for (unsigned int b = 0; b < boundMeshPlug.numElements(); b++) + { + MPlug p = boundMeshPlug.elementByLogicalIndex(b); + int at = p.name().indexW(meshId.c_str()); + + if (at < 0) + continue; + + boundMeshPlug = p; + } + + if (boundMeshPlug.isNull()) + { + AiMsgWarning("[%s] : %s.boundMesh plug is Null.", kTranslatorName, fnSplineBaseNode.name().asChar()); + continue; + } + + MPlug meshPlug = boundMeshPlug.source(); + MFnMesh fnMesh(meshPlug.node()); + string meshName = fnMesh.name().asChar(); + + AiMsgInfo(" meshId : %s", boundMeshPlug.name().asChar()); + + /*auto it = splineDataMap.find(meshName); + + if (it != splineDataMap.end()) { + cout << "[XgSplineDataTranslator] : Initial splineDataMap : " << meshName.c_str() << endl; + SplineData splineData; + splineDataMap[meshName] = splineData; + }*/ + + for (unsigned int p = 0; p < primitiveCount; p++) + { + const unsigned int offset = primitiveInfos[p * stride]; + const unsigned int length = primitiveInfos[p * stride + 1]; + + AiMsgDebug(" offset : %d", offset); + AiMsgDebug(" length : %d", length); + + MPointArray curve_pts; + + for (unsigned int i = 0; i < length; i++) + { + SgVec3f p = positions[i + offset]; + MPoint cpt(p[0], p[1], p[2]); + curve_pts.append(cpt); + } + splineData.push_back(curve_pts); + } + } + + AiMsgInfo("-------------------------------------"); + AiMsgInfo(" Spline Count : %d", splineData.size()); + AiMsgInfo("-------------------------------------"); +} + +void GetSplineData(string description, SplineDataMap &splineDataMap, unsigned int step, bool debug) +{ + // SplineDataMap splineDataMap; + + AiMsgInfo("[%s] : GetSplineData() : %s", kTranslatorName, description.c_str()); + + MSelectionList selList; + selList.clear(); + selList.add(MString(description.c_str())); + MDagPath descDagPath; + selList.getDagPath(0, descDagPath); + MObject descNode; + selList.getDependNode(0, descNode); + + if (!descDagPath.isValid()) + { + AiMsgWarning("[%s] : %s is invalid.", kTranslatorName, description.c_str()); + } + + MFnDagNode fnDagNode(descDagPath); + static const MString sApplyRenderOverrideCmd = "xgmSplineApplyRenderOverride "; + MGlobal::executeCommand(sApplyRenderOverrideCmd + fnDagNode.partialPathName()); + + MObject splineBase; + GetSplineBaseNode(descNode, splineBase); + + MFnDependencyNode fnSplineBaseNode(splineBase); + + AiMsgDebug("-------------------------------------"); + AiMsgDebug("[%s] : xgmSplineDescription : %s", kTranslatorName, fnDagNode.partialPathName().asChar()); + AiMsgDebug("[%s] : xgmSplineBase : %s", kTranslatorName, fnSplineBaseNode.name().asChar()); + AiMsgDebug("-------------------------------------"); + + // Init mesh spline data map + MPlug boundMeshPlug = fnSplineBaseNode.findPlug("boundMesh", true); + + if (boundMeshPlug.numElements() == 0) + AiMsgWarning("[%s] : xgmSplineBase : No mesh connect to the %s.boundMesh", kTranslatorName, fnSplineBaseNode.name().asChar()); + + AiMsgInfo("[%s] : init splineDataMap", kTranslatorName); + + for (unsigned int b = 0; b < boundMeshPlug.numElements(); b++) + { + MPlug p = boundMeshPlug.elementByLogicalIndex(b); + MPlug meshPlug = p.source(); + if (meshPlug.isNull()) + continue; + MFnMesh fnMesh(meshPlug.node()); + string meshName = fnMesh.name().asChar(); + SplineData splineData; + splineDataMap[meshName] = splineData; + + AiMsgInfo("[%s] : splineDataMap : %s", kTranslatorName, meshName.c_str()); + } + AiMsgInfo("-------------------------------------"); + + std::string data; + MPlug outPlug = fnDagNode.findPlug("outRenderData"); + MObject outObj = outPlug.asMObject(); + MPxData *outData = MFnPluginData(outObj).data(); + + if (outData) + { + std::ostringstream opaqueStrm; + outData->writeBinary(opaqueStrm); + data = opaqueStrm.str(); + // cout << data << endl; + } + + // Compute the padding bytes and number of array elements + const unsigned int tail = data.size() % sizeof(unsigned int); + const unsigned int padding = (tail > 0) ? sizeof(unsigned int) - tail : 0; + const unsigned int nelements = (unsigned int)data.size() / sizeof(unsigned int) + (tail > 0 ? 1 : 0); + + const size_t sampleSize = size_t(nelements) * sizeof(unsigned int) - padding; + + AiMsgDebug(" tail : %s", tail); + AiMsgDebug(" padding : %s", padding); + AiMsgDebug(" nelements : %s", nelements); + AiMsgDebug(" sampleSize : %s", sampleSize); + + XgFnSpline splines; + + double frame; + MString cmd("currentTime -query"); + MGlobal::executeCommand(cmd, frame); + + // std::stringstream opaqueStrm; + // opaqueStrm.write(data.c_str(), sampleSize); + if (!splines.load(std::stringstream(data), sampleSize, (float)frame)) + { + AiMsgWarning("[%s] Failed to load sample.", kTranslatorName); + } + + // Process multiplier and density mask + splines.executeScript(); + + for (XgItSpline splineIt = splines.iterator(); !splineIt.isDone(); splineIt.next()) + { + const unsigned int stride = splineIt.primitiveInfoStride(); + const unsigned int primitiveCount = splineIt.primitiveCount(); + const unsigned int *primitiveInfos = splineIt.primitiveInfos(); + const SgVec3f *positions = splineIt.positions(0); +#if defined(XGEN_SPLINE_API_VERSION) && XGEN_SPLINE_API_VERSION >= XGEN_SPLINE_VERSION_2017_UPDATE3 + const SgVec3f *directions = splineIt.widthDirection(0); +#endif + AiMsgDebug(" stride : %d, primitiveCount : %d, meshId : %s", stride, primitiveCount, splineIt.boundMeshId()); + + string meshId = splineIt.boundMeshId(); + MPlug boundMeshPlug = fnSplineBaseNode.findPlug("boundMesh", true); + + if (boundMeshPlug.numElements() == 0) + AiMsgWarning("[%s] : xgmSplineBase : No mesh connect to the %s.boundMesh.", kTranslatorName, fnSplineBaseNode.name().asChar()); + + for (unsigned int b = 0; b < boundMeshPlug.numElements(); b++) + { + MPlug p = boundMeshPlug.elementByLogicalIndex(b); + int at = p.name().indexW(meshId.c_str()); + + if (at < 0) + continue; + + boundMeshPlug = p; + } + + if (boundMeshPlug.isNull()) + { + AiMsgWarning("[%s] : %s.boundMesh plug is Null.", kTranslatorName, fnSplineBaseNode.name().asChar()); + continue; + } + + MPlug meshPlug = boundMeshPlug.source(); + MFnMesh fnMesh(meshPlug.node()); + string meshName = fnMesh.name().asChar(); + + AiMsgDebug(" boundMeshPlug : %s", boundMeshPlug.name().asChar()); + + for (unsigned int p = 0; p < primitiveCount; p++) + { + const unsigned int offset = primitiveInfos[p * stride]; + const unsigned int length = primitiveInfos[p * stride + 1]; + + AiMsgDebug(" offset : %d", offset); + AiMsgDebug(" length : %d", length); + + MPointArray curve_pts; + + for (unsigned int i = 0; i < length; i++) + { + SgVec3f p = positions[i + offset]; + MPoint cpt(p[0], p[1], p[2]); + curve_pts.append(cpt); + } + splineDataMap[meshName].push_back(curve_pts); + } + } + + AiMsgInfo("-------------------------------------"); + + for (auto it = splineDataMap.begin(); it != splineDataMap.end(); it++) + AiMsgInfo(" Mesh : %s, Spline Count : %d", it->first.c_str(), it->second.size()); + + AiMsgInfo("-------------------------------------"); +} + +void GetSplineRootPoints(string description, MPointArray &pointArray, unsigned int step, bool debug) +{ + SplineData splineData; + GetSplineData(description, splineData, step, debug); + for (unsigned int i = 0; i < splineData.size(); i++) + { + MPointArray curve_pts = splineData[i]; + pointArray.append(curve_pts[0]); + } +} + +void GetSplineRootPoints(string description, PointArrayMap &rootPointArrayMap, unsigned int step, bool debug) +{ + AiMsgInfo("[%s] : GetSplineRootPoints() : %s", kTranslatorName, description.c_str()); + + SplineDataMap splineDataMap; + GetSplineData(description, splineDataMap, step, debug); + for (auto it = splineDataMap.begin(); it != splineDataMap.end(); it++) + { + MPointArray points; + string mesh = it->first; + SplineData splineData = it->second; + + for (unsigned int i = 0; i < splineData.size(); i++) + { + MPointArray curve_pts = splineData[i]; + points.append(curve_pts[0]); + } + rootPointArrayMap[mesh] = points; + } +} +void GetSplineRootNormals(string description, MVectorArray &vectorArray, unsigned int step, bool debug) +{ + MStatus status; + + PointArrayMap rootPointArrayMap; + GetSplineRootPoints(description, rootPointArrayMap, step, debug); + + for (auto it = rootPointArrayMap.begin(); it != rootPointArrayMap.end(); it++) + { + + string mesh = it->first; + + MPointArray rootPoints = it->second; + + MSelectionList selList; + selList.clear(); + selList.add(MString(mesh.c_str())); + MDagPath dagPath; + selList.getDagPath(0, dagPath); + + if (!dagPath.isValid()) + { + MGlobal::displayError(MString(description.c_str()) + " is invalid"); + continue; + } + if (!dagPath.hasFn(MFn::kMesh)) + { + MGlobal::displayError(MString(mesh.c_str()) + " is invalid"); + continue; + } + + MMeshIntersector intersector; + MMatrix matrix = dagPath.inclusiveMatrix(); + status = intersector.create(dagPath.node(), matrix); + if (status) + { + for (unsigned i = 0; i < rootPoints.length(); i++) + { + MPoint pt = rootPoints[i]; + MPointOnMesh pointInfo; + intersector.getClosestPoint(pt, pointInfo); + MFloatVector closestNormal = pointInfo.getNormal(); + closestNormal = closestNormal * -1; + vectorArray.append(closestNormal); + } + } + } +} + +void GetSplineRootNormals(string description, VectorArrayMap &rootNormalArrayMap, unsigned int step, bool debug) +{ + MStatus status; + + PointArrayMap rootPointArrayMap; + GetSplineRootPoints(description, rootPointArrayMap, step, debug); + + for (auto it = rootPointArrayMap.begin(); it != rootPointArrayMap.end(); it++) + { + MVectorArray normals; + string mesh = it->first; + + MPointArray rootPoints = it->second; + + MSelectionList selList; + selList.clear(); + selList.add(MString(mesh.c_str())); + MDagPath dagPath; + selList.getDagPath(0, dagPath); + + if (!dagPath.isValid()) + { + MGlobal::displayError(MString(description.c_str()) + " is invalid"); + continue; + } + if (!dagPath.hasFn(MFn::kMesh)) + { + MGlobal::displayError(MString(mesh.c_str()) + " is invalid"); + continue; + } + + MMeshIntersector intersector; + MMatrix matrix = dagPath.inclusiveMatrix(); + status = intersector.create(dagPath.node(), matrix); + if (status) + { + for (unsigned i = 0; i < rootPoints.length(); i++) + { + MPoint pt = rootPoints[i]; + MPointOnMesh pointInfo; + intersector.getClosestPoint(pt, pointInfo); + MFloatVector closestNormal = pointInfo.getNormal(); + closestNormal = closestNormal * -1; + normals.append(closestNormal); + } + rootNormalArrayMap[mesh] = normals; + } + } +} + +void GetSplineRootPointsAndNormals(string description, MPointArray &pointArray, MVectorArray &vectorArray, unsigned int step, bool debug) +{ + AiMsgInfo("[%s] : getSplineRootPointsAndNormals() : %s", kTranslatorName, description.c_str()); + + MStatus status; + + PointArrayMap rootPointArrayMap; + GetSplineRootPoints(description, rootPointArrayMap, step, debug); + + for (auto it = rootPointArrayMap.begin(); it != rootPointArrayMap.end(); it++) + { + + string mesh = it->first; + + MPointArray rootPoints = it->second; + + MSelectionList selList; + selList.clear(); + selList.add(MString(mesh.c_str())); + MDagPath dagPath; + selList.getDagPath(0, dagPath); + + if (!dagPath.isValid()) + { + MGlobal::displayError(MString(description.c_str()) + " is invalid"); + continue; + } + if (!dagPath.hasFn(MFn::kMesh)) + { + MGlobal::displayError(MString(mesh.c_str()) + " is invalid"); + continue; + } + + MMeshIntersector intersector; + MMatrix matrix = dagPath.inclusiveMatrix(); + status = intersector.create(dagPath.node(), matrix); + if (status) + { + for (unsigned i = 0; i < rootPoints.length(); i++) + { + MPoint pt = rootPoints[i]; + MPointOnMesh pointInfo; + intersector.getClosestPoint(pt, pointInfo); + MFloatVector closestNormal = pointInfo.getNormal(); + closestNormal = closestNormal * -1; + pointArray.append(pt); + vectorArray.append(closestNormal); + } + } + } +} + +void GetSplineBaseNode(MObject &desc, MObject &splineBase) +{ + MFnDependencyNode depNode(desc); + MPlug rootPlug = depNode.findPlug("inSplineData", true); + MItDependencyGraph dgIt(rootPlug, + MFn::kInvalid, + MItDependencyGraph::kUpstream, + MItDependencyGraph::kDepthFirst, + MItDependencyGraph::kPlugLevel); + dgIt.next(); + while (!dgIt.isDone()) + { + MPlug plug = dgIt.previousPlug(); + MObject node = plug.node(); + if (node.isNull()) + continue; + MFnDependencyNode depNode(node); + if (depNode.typeName() == "xgmSplineBase") + { + splineBase = node; + break; + } + dgIt.next(); + } +} + +MSelectionList GetSplineBaseMesh(MObject splineBase) +{ + MSelectionList meshList; + MFnDependencyNode fnSplineBaseNode(splineBase); + MString name = fnSplineBaseNode.name(); + MPlug boundMeshPlug = fnSplineBaseNode.findPlug("boundMesh"); + for (unsigned int i = 0; i < boundMeshPlug.numElements(); i++) + { + MPlug p = boundMeshPlug.elementByLogicalIndex(i); + MString n = p.name().asChar(); + MPlug meshPlug = p.source(); + if (meshPlug.isNull()) + continue; + meshList.add(meshPlug.node()); + } + return meshList; +} + +int GetSplineBaseSegement(MObject splineBase) +{ + MFnDependencyNode fnSplineBaseNode(splineBase); + MPlug cvCountPlug = fnSplineBaseNode.findPlug("cvCount"); + int cvCount = cvCountPlug.asInt(); + return cvCount; +} \ No newline at end of file diff --git a/src/apCurveSample/extension/Xgen.h b/src/apCurveSample/extension/Xgen.h new file mode 100644 index 0000000..a9969bf --- /dev/null +++ b/src/apCurveSample/extension/Xgen.h @@ -0,0 +1,82 @@ +#pragma once +#include "define.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if MAYA_APP_VERSION < 2020 +#include +#include +#else +#include +#include +#endif + +#include +#include +#include +#include +#define XGEN_SPLINE_VERSION_2017_UPDATE3 201740 + +using namespace std; +using namespace XGenSplineAPI; + +void GetSplineData(string description, SplineData &splineData, unsigned int step = 0, bool debug = false); +void GetSplineData(string description, SplineDataMap &splineDataMap, unsigned int step = 0, bool debug = false); + +void GetSplineRootPoints(string description, MPointArray &pointArray, unsigned int step = 0, bool debug = false); +void GetSplineRootPoints(string description, PointArrayMap &pointArrayMap, unsigned int step = 0, bool debug = false); + +void GetSplineRootNormals(string description, VectorArrayMap &vectorArrayMap, unsigned int step = 0, bool debug = false); +void GetSplineRootNormals(string description, MVectorArray &vectorArray, unsigned int step = 0, bool debug = false); + +void GetSplineRootPointsAndNormals(string description, MPointArray &pointArray, MVectorArray &vectorArray, unsigned int step = 0, bool debug = false); + +void GetSplineBaseNode(MObject &desc, MObject &splineBase); + +MSelectionList GetSplineBaseMesh(MObject splineBase); + +int GetSplineBaseSegement(MObject splineBase); + +class XGenHelper +{ +public: + XGenHelper() = default; + XGenHelper(MObject &desc); + XGenHelper(MDagPath &descPath); + XGenHelper(string descName); + ~XGenHelper(); + + void GetSplineData(SplineDataMap &splineDataMap, unsigned int step = 0); + void GetSplineRootPoints(PointArrayMap &pointArrayMap, unsigned int step = 0); + void GetSplineRootNormals(VectorArrayMap &vectorArrayMap, unsigned int step = 0); + void GetSplineRootPointsAndNormals(MPointArray &pointArray, MVectorArray &vectorArray, unsigned int step = 0); + MObjectArray GetSplineBaseMesh(); + int GetBaseSegment(); + // void GetSplineBase(); + // void GetSplineBase(MObject &splineBase); + MObject GetSplineBase(); + void SetDebug(bool debug) { m_debug = debug; }; + bool HasBoundMesh(); + MObject &Get() { return m_description; }; + MDagPath &GetDescDagPath() { return m_descPath; }; + MString GetDescName(bool fullPathName = false); + MString GetSplineBaseName(); + +private: + MObject m_description; + MDagPath m_descPath; + // MObject m_splineBase; + bool m_debug; +}; \ No newline at end of file diff --git a/src/apCurveSample/extension/apCurveDataTranslate.py b/src/apCurveSample/extension/apCurveDataTranslate.py new file mode 100644 index 0000000..f8a8c95 --- /dev/null +++ b/src/apCurveSample/extension/apCurveDataTranslate.py @@ -0,0 +1,2 @@ +import mtoa.ui.ae.templates as templates +from mtoa.ui.ae.templates import ShapeTranslatorTemplate, registerTranslatorUI, AttributeTemplate diff --git a/src/apCurveSample/extension/define.h b/src/apCurveSample/extension/define.h new file mode 100644 index 0000000..cb48793 --- /dev/null +++ b/src/apCurveSample/extension/define.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include + + +#include +#include +#include +#include +#include + +#define kTranslatorName "CurveDataTranslator" + +using namespace std; + +typedef vector SplineData; +typedef map SplineDataMap; + +typedef map IndexArrayMap; +typedef map PointArrayMap; +typedef map VectorArrayMap; +typedef pair PointVectorPair; +typedef map PointVectorArrayMap; +typedef vector PointArray; +typedef vector VectorArray; + +typedef vector StringArray; +typedef vector IntArray; + +typedef StringArray MeshArray; + +typedef vector DagPathArray; + +typedef IndexArrayMap IndexArrayMap; +typedef VectorArrayMap VectorArrayMap; diff --git a/src/apCurveSample/extension/utils.cpp b/src/apCurveSample/extension/utils.cpp new file mode 100644 index 0000000..854f66b --- /dev/null +++ b/src/apCurveSample/extension/utils.cpp @@ -0,0 +1,126 @@ +#include "utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +MStatus GetMayaObject(std::string name, MObject &object) +{ + MSelectionList s_list; + s_list.clear(); + s_list.add(name.c_str()); + return s_list.getDependNode(0, object); +}; + +MStatus GetMayaDagPath(std::string name, MDagPath &dagPath) +{ + MSelectionList s_list; + s_list.clear(); + s_list.add(name.c_str()); + return s_list.getDagPath(0, dagPath); +}; + +MStatus GetMayaDagPath(MObject& object, MDagPath& dagPath) +{ + MSelectionList s_list; + s_list.clear(); + s_list.add(object); + return s_list.getDagPath(0, dagPath); +} + +MObjectArray ListTypedNodes(MFn::Type filter) +{ + MStatus status; + MObjectArray nodes; + MItDependencyNodes iterNode(filter); + iterNode.reset(); + while (!iterNode.isDone()) + { + nodes.append(iterNode.item()); + iterNode.next(); + } + return nodes; +} + +MObjectArray GetTypeNodes(MObject rootNode, + MItDependencyGraph::Direction direction, + MFn::Type filter) +{ + MStatus status; + MObjectArray nodeList; + MItDependencyGraph iterDG(rootNode, filter, + direction, + MItDependencyGraph::kDepthFirst, + MItDependencyGraph::Level::kNodeLevel, + &status); + iterDG.reset(); + while (!iterDG.isDone()) + { + MObject item = iterDG.currentItem(); + if (item.isNull()) + continue; + nodeList.append(item); + iterDG.next(); + } + return nodeList; +} + +MObjectArray GetTypeNodes(MPlug rootPlug, + MItDependencyGraph::Direction direction, + MFn::Type filter) +{ + MStatus status; + MObjectArray nodeList; + MItDependencyGraph iterDG(rootPlug, filter, + direction, + MItDependencyGraph::kDepthFirst, + MItDependencyGraph::Level::kNodeLevel, + &status); + iterDG.reset(); + while (!iterDG.isDone()) + { + MObject item = iterDG.currentItem(); + if (item.isNull()) + continue; + nodeList.append(item); + iterDG.next(); + } + return nodeList; +} + +MObjectArray GetTypeNodes(MPlug rootPlug, MString nodeTypeName, + MItDependencyGraph::Direction direction, + MFn::Type filter) +{ + MStatus status; + MObjectArray nodeList; + MItDependencyGraph iterDG(rootPlug, filter, + direction, + MItDependencyGraph::kDepthFirst, + MItDependencyGraph::Level::kNodeLevel, + &status); + iterDG.reset(); + while (!iterDG.isDone()) + { + MObject item = iterDG.currentItem(); + if (item.isNull()) + continue; + MFnDependencyNode fnNode(item); + if (fnNode.typeName() == nodeTypeName) + { + nodeList.append(item); + } + iterDG.next(); + } + return nodeList; +} + + diff --git a/src/apCurveSample/extension/utils.h b/src/apCurveSample/extension/utils.h new file mode 100644 index 0000000..0c87ad8 --- /dev/null +++ b/src/apCurveSample/extension/utils.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +MStatus GetMayaObject(std::string name, MObject& object); +MStatus GetMayaDagPath(std::string name, MDagPath& dagPath); +MStatus GetMayaDagPath(MObject& object, MDagPath& dagPath); + +MObjectArray ListTypedNodes(MFn::Type filter = MFn::kInvalid); + +MObjectArray GetTypeNodes(MObject rootNode, + MItDependencyGraph::Direction direction = MItDependencyGraph::kDownstream, + MFn::Type filter = MFn::kInvalid); +MObjectArray GetTypeNodes(MPlug rootPlug, + MItDependencyGraph::Direction direction = MItDependencyGraph::kDownstream, + MFn::Type filter = MFn::kInvalid); +MObjectArray GetTypeNodes(MPlug rootPlug, MString nodeTypeName, + MItDependencyGraph::Direction direction = MItDependencyGraph::kDownstream, + MFn::Type filter = MFn::kInvalid); diff --git a/src/apCurveSample/shader/CMakeLists.txt b/src/apCurveSample/shader/CMakeLists.txt new file mode 100644 index 0000000..90e7366 --- /dev/null +++ b/src/apCurveSample/shader/CMakeLists.txt @@ -0,0 +1,23 @@ +project(apCurveSample) + +set(SRC_FILES + "apCurveSample.cpp") + +set(META_FILES + "apCurveSample.mtd") + +set(TEMPLATE_FILES + "apCurveSampleTemplate.py") + +include_directories(${ARNOLD_INCLUDE_PATH}) +add_library(${PROJECT_NAME} SHARED ${SRC_FILES}) +set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "") + +target_link_libraries(${PROJECT_NAME} ${ARNOLD_AI_LIBRARY}) + +set(INSTALL_SHADER_TARGET "${CMAKE_INSTALL_PREFIX}/${ARNOLD_VERSION}/${CMAKE_PROJECT_NAME}/shaders") +set(INSTALL_TEMPLATE_TARGET "${CMAKE_INSTALL_PREFIX}/${ARNOLD_VERSION}/${CMAKE_PROJECT_NAME}/templates") + +install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${INSTALL_SHADER_TARGET}) +install(FILES ${META_FILES} DESTINATION ${INSTALL_SHADER_TARGET}) +install(FILES ${TEMPLATE_FILES} DESTINATION ${INSTALL_TEMPLATE_TARGET}) \ No newline at end of file diff --git a/src/apCurveSample/shader/apCurveSample.cpp b/src/apCurveSample/shader/apCurveSample.cpp new file mode 100644 index 0000000..874ecca --- /dev/null +++ b/src/apCurveSample/shader/apCurveSample.cpp @@ -0,0 +1,502 @@ +#include +#include +#include +#include + +AI_SHADER_NODE_EXPORT_METHODS(apCurveSample) + +using namespace std; + +enum apCurveSampleParams +{ + p_sample_data_type, + p_normalize, + p_trace_sets, + p_ray_offset, + p_ray_max_depth, + p_ray_max_sample, + p_occ_min_dist, + p_occ_max_dist, + p_occ_spread, + p_occ_falloff, + p_error_color, + p_verbose, + p_debug +}; +static const char *SampleFromNames[] = { + "Shading Point", + "Root Point"}; + +static const char *SampleDataTypeNames[] = { + "Shading Color", + "Shading Normal (N)", + "Shading Normal without Bump (Ns)", + "Geometry Normal (Ng)", + "Shading Normal face-forward (Nf)", + "Geometry Normal face-forward (Ngf)", + "Shading Point (P)", + "UV Coordinate (uv)", + "Tanget U (dPdu)", + "Tanget V (dPdv)", + "Binormal (dPdu ^ dPdv)", + "Distance (Rl)", + "Occlusion"}; + +enum SampleDataType +{ + SHADING_COLOR = 0, + SHADING_NORMAL, + SHADING_NORMAL_WITHOUT_BUMP, + GEOMETRY_NORMAL, + SHADING_NORMAL_FACE_FORWARD, + GEOMETRY_NORMAL_FACE_FORWARD, + SHADING_POINT, + UV_COORD, + TANGENT_U, + TANGENT_V, + BINORMAL, + DISTANCE, + OCCLUSION +}; + +struct ShaderData +{ + AtSampler *sampler; + int sample_data_type; + bool normalize; + AtString trace_set; + float ray_offset; + int ray_max_depth; + int ray_max_sample; + float occ_min_dist; + float occ_max_dist; + float occ_spread; + float occ_falloff; + bool verbose; + int ray_count = 0; +}; + +bool string_contain(AtString str, AtArray *array) +{ + + int nelement = AiArrayGetNumElements(array); + for (int i = 0; i < nelement; i++) + { + AtString name = AiArrayGetStr(array, i); + if (name == str) + return true; + } + return false; +} + +node_parameters +{ + AiParameterEnum("sample_data_type", 0, SampleDataTypeNames); + AiParameterBool("normalize", false); + AiParameterStr("trace_set", "curve_sample_set"); + AiParameterFlt("ray_offset", 0.5); + AiParameterInt("ray_max_depth", 30); + AiParameterInt("ray_max_sample", 3); + AiParameterFlt("occ_min_dist", 0.0); + AiParameterFlt("occ_max_dist", 100.0); + AiParameterFlt("occ_spread", 1.0); + AiParameterFlt("occ_falloff", 0.0); + AiParameterRGB("error_color", 1.0, 0.0, 1.0); + AiParameterBool("verbose", false); +} + +node_initialize +{ + ShaderData *data = (ShaderData *)AiMalloc(sizeof(ShaderData)); + const int seed = 3158863998; + const int nsamples = 1; + const int ndim = 3; + data->sampler = AiSampler(seed, nsamples, ndim); + AiNodeSetLocalData(node, data); +} + +node_finish +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AiFree(data); +} + +node_update +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + data->sample_data_type = AiNodeGetInt(node, "sample_data_type"); + data->normalize = AiNodeGetBool(node, "normalize"); + data->trace_set = AiNodeGetStr(node, "trace_set"); + data->ray_offset = AiNodeGetFlt(node, "ray_offset"); + data->ray_max_depth = AiNodeGetInt(node, "ray_max_depth"); + data->ray_max_sample = AiNodeGetInt(node, "ray_max_sample"); + data->occ_min_dist = AiNodeGetFlt(node, "occ_min_dist"); + data->occ_max_dist = AiNodeGetFlt(node, "occ_max_dist"); + data->occ_spread = AiNodeGetFlt(node, "occ_spread"); + data->occ_falloff = AiNodeGetFlt(node, "occ_falloff"); + data->verbose = AiNodeGetBool(node, "verbose"); +} + +shader_evaluate +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + + float error_threshold = 1.0; + + string node_entry_name = AiNodeEntryGetName(AiNodeGetNodeEntry(node)); + + AtNode *shade_object = sg->Op; + string shade_object_name = AiNodeGetName(shade_object); + // AiMsgInfo("[%s] : Shading object : %s", node_entry_name.c_str(), shade_object_name.c_str()); + if (!AiNodeIs(shade_object, AtString("curves"))) + { + if (data->verbose) + { + const AtNodeEntry *shade_object_entry = AiNodeGetNodeEntry(shade_object); + string shade_object_entry_name = AiNodeEntryGetName(shade_object_entry); + AiMsgWarning("[%s] : Shading object %s is not curve : (%s)", node_entry_name.c_str(), shade_object_name.c_str(), shade_object_entry_name.c_str()); + } + sg->out.RGB() = AiShaderEvalParamRGB(p_error_color); + return; + } + + AtUniverse *universe = AiNodeGetUniverse(node); + AtNode *option = AiUniverseGetOptions(universe); + + // string base_object_name = shade_object_name.substr(0, shade_object_name.length() - 7); + string base_object_name = shade_object_name; + string cv_count_param = base_object_name + "_cv_count"; + + if (!AiNodeLookUpUserParameter(option, cv_count_param.c_str())) + { + AiMsgWarning("Failed to access cv_count parameter : %s", cv_count_param.c_str()); + sg->out.RGB() = AiShaderEvalParamRGB(p_error_color); + return; + } + + int cv_count = AiNodeGetInt(option, cv_count_param.c_str()); + + if (!cv_count) + { + AiMsgWarning("Invalid CV count (cv_count) : %d", cv_count); + sg->out.RGB() = AiShaderEvalParamRGB(p_error_color); + return; + } + + int curve_id = (sg->fi) / (cv_count - 1); + string mesh_names_param = base_object_name + "_meshs"; + AtArray *mesh_names = AiNodeGetArray(option, mesh_names_param.c_str()); + + if (mesh_names == nullptr) + { + AiMsgWarning("Failed to access parameter : %s", mesh_names_param.c_str()); + sg->out.RGB() = AiShaderEvalParamRGB(p_error_color); + return; + } + + string root_point_param = base_object_name + "_points"; + AtArray *root_points = AiNodeGetArray(option, root_point_param.c_str()); + + if (root_points == nullptr) + { + AiMsgWarning("Failed to get root points (NULL) : %s", root_point_param.c_str()); + sg->out.RGB() = AiShaderEvalParamRGB(p_error_color); + return; + } + + string root_normal_param = base_object_name + "_normals"; + AtArray *root_normals = AiNodeGetArray(option, root_normal_param.c_str()); + + if (root_normals == nullptr) + { + AiMsgWarning("Failed to get root normals (NULL) : %s", root_normal_param.c_str()); + sg->out.RGB() = AiShaderEvalParamRGB(p_error_color); + return; + } + + int nelement = AiArrayGetNumElements(root_points); + + if (nelement == 0) + { + AiMsgWarning("Invalid root point count : %s", nelement); + sg->out.RGB() = AiShaderEvalParamRGB(p_error_color); + return; + } + + if (sg->Rt & AI_RAY_SHADOW) + return; + + int trace_depth = 0; + int trace_sample = 0; + + AtRGB outColor = AI_RGB_BLACK; + AtString trace_set = AiShaderEvalParamStr(p_trace_sets); + + AtVector rp = AiArrayGetVec(root_points, curve_id); + AtVector rn = AiArrayGetVec(root_normals, curve_id); + + // Ray source is from root point + negative root_normal direction * ray_offset + AtVector rs = rp + AiV3Normalize(-1 * rn) * data->ray_offset; + + // Ray direction initialize from root normal + AtVector dir = rn; + + if (data->verbose) + { + AiMsgInfo(" ray : rs : %f, %f, %f", rs.x, rs.y, rs.z); + AiMsgInfo(" ray : dir : %f, %f, %f", dir.x, dir.y, dir.z); + } + + AiShaderGlobalsSetTraceSet(sg, trace_set, false); + + while (true) + { + if (data->ray_max_depth > 0 && trace_depth > data->ray_max_depth) + { + if (data->verbose) + AiMsgInfo("[%s][%d] : Trace over max depth %d : %d", node_entry_name.c_str(), data->ray_max_depth, trace_depth); + break; + } + if (trace_sample > data->ray_max_sample) + { + if (data->verbose) + AiMsgInfo("[%s][%d] : Resample over max sample %d : %d", node_entry_name.c_str(), curve_id, data->ray_max_sample, trace_sample); + break; + } + + AtRay ray = AiMakeRay(AI_RAY_SPECULAR_REFLECT, rs, &dir, AI_BIG, sg); + + if (data->sample_data_type == SampleDataType::SHADING_COLOR) + { + AtScrSample hit_color; + if (!AiTrace(ray, AtRGB(1.0), hit_color)) + break; + + AtVector current_hit_point = hit_color.point; + const AtNode *hit_object = hit_color.obj; + const AtNodeEntry *hit_object_entry = AiNodeGetNodeEntry(hit_object); + string hit_node_entry_name = AiNodeEntryGetName(hit_object_entry); + string hit_object_name = AiNodeGetName(hit_object); + + bool pass_through = false; + + if (hit_node_entry_name == "curves") + pass_through = true; + + if (!pass_through) + { + AtString hit_shade_object_name(hit_object_name.c_str()); + if (!string_contain(hit_shade_object_name, mesh_names)) + { + if (data->verbose) + AiMsgInfo("[%s][%d] : hit object %s not in the mesh list", node_entry_name.c_str(), curve_id, hit_shade_object_name); + pass_through = true; + } + } + + if (pass_through) + { + rs = hit_color.point; + trace_depth++; + continue; + } + + float dst_length = AiV3Length(current_hit_point - rp); + + if (dst_length > error_threshold) + { + trace_sample++; + + if (data->verbose) + { + AiMsgInfo("[%s][%d] : Trace length is over %f (%f)", node_entry_name.c_str(), curve_id, error_threshold, dst_length); + AiMsgInfo("[%s][%d] : Resampling : (%d/%d)", node_entry_name.c_str(), curve_id, trace_sample, data->ray_max_sample); + } + + AtSamplerIterator *iterator = AiSamplerIterator(data->sampler, sg); + AtVector rnd; + + if (AiSamplerGetSample(iterator, &rnd.x)) + { + rs = (rp + AiV3Normalize(-1 * rn) * data->ray_offset) + (rnd * 0.01f); + } + + if (data->verbose) + { + AiMsgInfo(" rnd : %f, %f, %f", rnd.x, rnd.y, rnd.z); + AiMsgInfo(" rp : %f, %f, %f", rp.x, rp.y, rp.z); + AiMsgInfo(" rs : %f, %f, %f", rs.x, rs.y, rs.z); + } + continue; + } + + outColor = hit_color.color; + break; + } + + if (data->sample_data_type >= SampleDataType::SHADING_NORMAL) + { + AtShaderGlobals *hit_point = AiShaderGlobals(); + if (!AiTraceProbe(ray, hit_point)) + { + AiShaderGlobalsDestroy(hit_point); + break; + } + + AtVector current_hit_point = hit_point->P; + AtNode *hit_object = hit_point->Op; + const AtNodeEntry *hit_object_entry = AiNodeGetNodeEntry(hit_object); + string hit_node_entry_name = AiNodeEntryGetName(hit_object_entry); + string hit_object_name = AiNodeGetName(hit_object); + + bool pass_through = false; + + if (hit_node_entry_name == "curves") + pass_through = true; + + if (pass_through) + { + rs = current_hit_point; + trace_depth++; + + AiShaderGlobalsDestroy(hit_point); + continue; + } + + float dst_length = AiV3Length(current_hit_point - rp); + + if (dst_length > error_threshold) + { + trace_sample++; + + if (data->verbose) + { + AiMsgInfo("[%s][%d] : Trace length is over %f (%f)", node_entry_name.c_str(), curve_id, error_threshold, dst_length); + AiMsgInfo("[%s][%d] : Resampling : (%d/%d)", node_entry_name.c_str(), curve_id, trace_sample, data->ray_max_sample); + } + + AtSamplerIterator *iterator = AiSamplerIterator(data->sampler, sg); + AtVector rnd; + + if (AiSamplerGetSample(iterator, &rnd.x)) + { + rs = (rp + AiV3Normalize(-1 * rn) * data->ray_offset) + (rnd * 0.01f); + } + + if (data->verbose) + { + AiMsgInfo(" rnd : %f, %f, %f", rnd.x, rnd.y, rnd.z); + AiMsgInfo(" rp : %f, %f, %f", rp.x, rp.y, rp.z); + AiMsgInfo(" rs : %f, %f, %f", rs.x, rs.y, rs.z); + } + + switch (data->sample_data_type) + { + case SampleDataType::SHADING_NORMAL: + { + AtVector n = hit_point->N; + if (data->normalize) + n = AiV3Normalize(n); + outColor = AtRGB(n.x, n.y, n.z); + break; + } + case SampleDataType::SHADING_NORMAL_WITHOUT_BUMP: + { + AtVector n = hit_point->Ns; + if (data->normalize) + n = AiV3Normalize(n); + outColor = AtRGB(n.x, n.y, n.z); + break; + } + case SampleDataType::SHADING_NORMAL_FACE_FORWARD: + { + AtVector n = hit_point->Nf; + if (data->normalize) + n = AiV3Normalize(n); + outColor = AtRGB(n.x, n.y, n.z); + break; + } + case SampleDataType::GEOMETRY_NORMAL: + { + AtVector n = hit_point->Ng; + if (data->normalize) + n = AiV3Normalize(n); + outColor = AtRGB(n.x, n.y, n.z); + break; + } + case SampleDataType::GEOMETRY_NORMAL_FACE_FORWARD: + { + AtVector n = hit_point->Ngf; + if (data->normalize) + n = AiV3Normalize(n); + outColor = AtRGB(n.x, n.y, n.z); + break; + } + case SampleDataType::SHADING_POINT: + { + outColor = AtRGB(hit_point->P.x, hit_point->P.y, hit_point->P.z); + break; + } + case SampleDataType::UV_COORD: + { + outColor = AtRGB(hit_point->u, hit_point->v, 0.0f); + break; + } + case SampleDataType::TANGENT_U: + { + AtVector tu; + if (data->normalize) + tu = AiV3Normalize(hit_point->dPdu); + outColor = AtRGB(tu.x, tu.y, tu.z); + break; + } + case SampleDataType::TANGENT_V: + { + AtVector tv; + if (data->normalize) + tv = AiV3Normalize(hit_point->dPdv); + outColor = AtRGB(tv.x, tv.y, tv.z); + break; + } + case SampleDataType::BINORMAL: + { + AtVector binormal = AiV3Cross(hit_point->dPdv, hit_point->dPdv); + if (data->normalize) + binormal = AiV3Normalize(binormal); + outColor = AtRGB(binormal.x, binormal.y, binormal.z); + break; + } + case SampleDataType::OCCLUSION: + { + outColor = AiOcclusion(hit_point->N, hit_point->Ng, hit_point, + data->occ_min_dist, data->occ_max_dist, data->occ_spread, data->occ_falloff, + data->sampler, NULL); + break; + } + } + + AiShaderGlobalsDestroy(hit_point); + continue; + } + + AiShaderGlobalsDestroy(hit_point); + break; + } + } + + AiShaderGlobalsUnsetTraceSet(sg); + sg->out.RGB() = outColor; +} + +node_loader +{ + if (i > 0) + return false; + + node->methods = apCurveSample; + node->output_type = AI_TYPE_RGB; + node->name = "apCurveSample"; + node->node_type = AI_NODE_SHADER; + strcpy(node->version, AI_VERSION); + return true; +} diff --git a/src/apCurveSample/shader/apCurveSample.mtd b/src/apCurveSample/shader/apCurveSample.mtd new file mode 100644 index 0000000..8b47873 --- /dev/null +++ b/src/apCurveSample/shader/apCurveSample.mtd @@ -0,0 +1,62 @@ +[node apCurveSample] + maya.name STRING "apCurveSample" + maya.id INT 0x0005118 + maya.classification STRING "shader/texture" + +[attr sample_data_type] + desc STRING "Sample Data Type" + maya.keyable BOOL false + linkable BOOL true + +[attr normalize] + desc STRING "Normalize" + maya.keyable BOOL false + linkable BOOL false + +[attr trace_set] + desc STRING "Trace Sets" + maya.keyable BOOL false + linkable BOOL false + +[attr ray_offset] + desc STRING "Ray Offset" + maya.keyable BOOL false + linkable BOOL false + +[attr ray_max_depth] + desc STRING "Ray Max Depth" + maya.keyable BOOL false + linkable BOOL false +[attr ray_max_sample] + desc STRING "Ray Max Sample" + maya.keyable BOOL false + linkable BOOL false +[attr occ_min_dist] + desc STRING "Occlusion Min Dist" + maya.keyable BOOL false + linkable BOOL false + +[attr occ_max_dist] + desc STRING "Occlusion Max Dist" + maya.keyable BOOL false + linkable BOOL false + +[attr occ_spread] + desc STRING "Occlusion Spread" + maya.keyable BOOL false + linkable BOOL false + +[attr occ_falloff] + desc STRING "Occlusion Falloff" + maya.keyable BOOL false + linkable BOOL false + +[attr error_color] + desc STRING "Error Color" + maya.keyable BOOL false + linkable BOOL true + +[attr verbose] + desc STRING "Error Color" + maya.keyable BOOL false + linkable BOOL false \ No newline at end of file diff --git a/src/apCurveSample/shader/apCurveSampleTemplate.py b/src/apCurveSample/shader/apCurveSampleTemplate.py new file mode 100644 index 0000000..156fadd --- /dev/null +++ b/src/apCurveSample/shader/apCurveSampleTemplate.py @@ -0,0 +1,53 @@ +import pymel.core as pm +from mtoa.ui.ae.shaderTemplate import ShaderAETemplate + + +class AEapCurSampleTemplate(ShaderAETemplate): + def setup(self): + self.addSwatch() + + self.beginLayout("Sample", collapse=False) + self.addControl('sample_data_type', label='Sample Type', + annotation='Sample Type') + self.addControl('ray_offset', label='Ray Offset', + annotation='Ray Offset') + self.addControl('ray_max_sample', label='Ray Max Sample', + annotation='Ray Max Sample') + self.addControl('ray_max_depth', label='Ray Max Depth', + annotation='Ray Max Depth') + self.endLayout() + + self.beginLayout("Occlusion", collapse=False) + self.addControl('occ_min_dist', label='Occlusion Min Dist', + annotation='Occlusion Minimum Ray Distance') + self.addControl('occ_max_dist', label='Occlusion Max Dist', + annotation='Occlusion Maximum Ray Distance') + self.addControl('occ_spread', label='Occlusion Spread', + annotation='Angular spread around the normal vector') + self.addControl('occ_falloff', label='Occlusion Falloff', + annotation='Exponential falloff rate for the occlusion along the ray distance') + self.endLayout() + + self.beginLayout("Output", collapse=False) + self.addControl('sample_data_type', label='Sample Data Type', + annotation='Sample Data Type') + self.beginNoOptimize() + self.addControl('space', label='Space', + annotation='Normalize Output Vector') + self.addControl('normalize', label='Normalize', + annotation='Normalize Output Vector') + self.addControl('invert', label='Invert', + annotation='Invert Output Vector') + self.endNoOptimize() + self.endLayout() + + self.beginLayout("Render", collapse=False) + self.addControl('error_color', label='Error Color', + annotation='Error Color') + self.addControl('trace_sets', label='Trace Sets', + annotation='Trace Sets') + self.endLayout() + + pm.mel.AEdependNodeTemplate(self.nodeName) + self.addExtraControls() + self.endScrollLayout() diff --git a/src/apEntrySwitch/CMakeLists.txt b/src/apEntrySwitch/CMakeLists.txt new file mode 100644 index 0000000..4cb73e6 --- /dev/null +++ b/src/apEntrySwitch/CMakeLists.txt @@ -0,0 +1,23 @@ +set(SHADER apEntrySwitch) + +set(SRC_FILES + "apEntrySwitch.cpp") + +set(META_FILES + "apEntrySwitch.mtd") + +set(TEMPLATE_FILES + "apEntrySwitchTemplate.py") + +include_directories(${ARNOLD_INCLUDE_PATH}) +add_library(${SHADER} SHARED ${SRC_FILES}) +set_target_properties(${SHADER} PROPERTIES PREFIX "") + +target_link_libraries(${SHADER} ${ARNOLD_AI_LIBRARY}) + +set(INSTALL_SHADER_TARGET "${CMAKE_INSTALL_PREFIX}/${ARNOLD_VERSION}/${CMAKE_PROJECT_NAME}/shaders") +set(INSTALL_TEMPLATE_TARGET "${CMAKE_INSTALL_PREFIX}/${ARNOLD_VERSION}/${CMAKE_PROJECT_NAME}/templates") + +install(TARGETS ${SHADER} RUNTIME DESTINATION ${INSTALL_SHADER_TARGET}) +install(FILES ${META_FILES} DESTINATION ${INSTALL_SHADER_TARGET}) +install(FILES ${TEMPLATE_FILES} DESTINATION ${INSTALL_TEMPLATE_TARGET}) \ No newline at end of file diff --git a/src/apEntrySwitch/apEntrySwitch.cpp b/src/apEntrySwitch/apEntrySwitch.cpp new file mode 100644 index 0000000..670757f --- /dev/null +++ b/src/apEntrySwitch/apEntrySwitch.cpp @@ -0,0 +1,102 @@ +#include "ai.h" +#include + +AI_SHADER_NODE_EXPORT_METHODS(apEntrySwitch) + + enum apEntrySwitchParams { + p_entry_polymesh, + p_entry_curves, + p_entry_nurbs, + p_entry_point, + p_entry_volume, + p_default_color +}; + +struct ShaderData +{ + AtRGB entry_ploymesh; + AtRGB entry_curves; + AtRGB entry_nurbs; + AtRGB entry_point; + AtRGB entry_volume; + AtRGB default_color; +}; + +node_parameters +{ + AiParameterRGB("polymesh", 1, 0, 0); + AiParameterRGB("curves", 0, 1, 0); + AiParameterRGB("nurbs", 0, 0, 1); + AiParameterRGB("point", 0, 1, 1); + AiParameterRGB("volume", 1, 1, 0); + AiParameterRGB("default_color", 1, 0, 1); +} + +node_initialize +{ + ShaderData *data = (ShaderData*) AiMalloc(sizeof(ShaderData)); + data->entry_ploymesh = AtRGB(1.0, 0, 0); + data->entry_curves = AtRGB(0, 1.0, 0); + data->entry_nurbs = AtRGB(0, 0, 1.0); + data->entry_point = AtRGB(0, 1.0, 1.0); + data->entry_volume = AtRGB(1.0, 1.0, 0); + data->default_color = AtRGB(1.0, 0, 1.0); + AiNodeSetLocalData(node, data); +} +node_update +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + data->entry_ploymesh = AiNodeGetRGB(node, "polymesh"); + data->entry_curves = AiNodeGetRGB(node, "curves"); + data->entry_nurbs = AiNodeGetRGB(node, "nurbs"); + data->entry_point = AiNodeGetRGB(node, "point"); + data->entry_volume = AiNodeGetRGB(node, "volume"); + data->default_color = AiNodeGetRGB(node, "default_color"); +} + +node_finish +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AiFree(data); +} + +shader_evaluate +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AtString entry_name(AiNodeEntryGetName(AiNodeGetNodeEntry(sg->Op))); + + if (entry_name == AtString("polymesh")) { + sg->out.RGB() = data->entry_ploymesh; + return; + } + if (entry_name == AtString("curves")) { + sg->out.RGB() = data->entry_curves; + return; + } + if (entry_name == AtString("nurbs")) { + sg->out.RGB() = data->entry_nurbs; + return; + } + if (entry_name == AtString("point")) { + sg->out.RGB() = data->entry_point; + return; + } + if (entry_name == AtString("volume")) { + sg->out.RGB() = data->entry_volume; + return; + } + sg->out.RGB() = data->default_color; + return; +} +node_loader +{ + if (i > 0) + return false; + + node->methods = apEntrySwitch; + node->output_type = AI_TYPE_RGBA; + node->name = "apEntrySwitch"; + node->node_type = AI_NODE_SHADER; + strcpy(node->version, AI_VERSION); + return true; +} \ No newline at end of file diff --git a/src/apEntrySwitch/apEntrySwitch.mtd b/src/apEntrySwitch/apEntrySwitch.mtd new file mode 100644 index 0000000..b306887 --- /dev/null +++ b/src/apEntrySwitch/apEntrySwitch.mtd @@ -0,0 +1,34 @@ +[node apEntrySwitch] + maya.name STRING "apEntrySwitch" + maya.id INT 0x0005102 + maya.classification STRING "shader/surface" + [attr polymesh] + desc STRING "Entry polymesh" + maya.keyable BOOL false + linkable BOOL true + + [attr curves] + desc STRING "Entry curves" + maya.keyable BOOL false + linkable BOOL true + + [attr nurbs] + desc STRING "Entry nurbs" + maya.keyable BOOL false + linkable BOOL true + + [attr point] + desc STRING "Entry point" + maya.keyable BOOL false + linkable BOOL false + + [attr volume] + desc STRING "Entry volume" + maya.keyable BOOL false + linkable BOOL false + + [attr default_color] + desc STRING "Default Color" + maya.keyable BOOL false + linkable BOOL true + diff --git a/src/apEntrySwitch/apEntrySwitchTemplate.py b/src/apEntrySwitch/apEntrySwitchTemplate.py new file mode 100644 index 0000000..e69de29 diff --git a/src/apGrayBall/CMakeLists.txt b/src/apGrayBall/CMakeLists.txt new file mode 100644 index 0000000..e576bc3 --- /dev/null +++ b/src/apGrayBall/CMakeLists.txt @@ -0,0 +1,24 @@ +set(SHADER apGrayBall) + +set(SRC_FILES + "apGrayBall.h" + "apGrayBall.cpp") + +set(META_FILES + "apGrayBall.mtd") + +set(TEMPLATE_FILES + "apGrayBallTemplate.py") + +include_directories(${ARNOLD_INCLUDE_PATH}) +add_library(${SHADER} SHARED ${SRC_FILES}) +set_target_properties(${SHADER} PROPERTIES PREFIX "") + +target_link_libraries(${SHADER} ${ARNOLD_AI_LIBRARY}) + +set(INSTALL_SHADER_TARGET "${CMAKE_INSTALL_PREFIX}/${ARNOLD_VERSION}/${CMAKE_PROJECT_NAME}/shaders") +set(INSTALL_TEMPLATE_TARGET "${CMAKE_INSTALL_PREFIX}/${ARNOLD_VERSION}/${CMAKE_PROJECT_NAME}/templates") + +install(TARGETS ${SHADER} RUNTIME DESTINATION ${INSTALL_SHADER_TARGET}) +install(FILES ${META_FILES} DESTINATION ${INSTALL_SHADER_TARGET}) +install(FILES ${TEMPLATE_FILES} DESTINATION ${INSTALL_TEMPLATE_TARGET}) \ No newline at end of file diff --git a/src/apGrayBall/apGrayBall.cpp b/src/apGrayBall/apGrayBall.cpp new file mode 100644 index 0000000..cd728ac --- /dev/null +++ b/src/apGrayBall/apGrayBall.cpp @@ -0,0 +1,92 @@ +#include "apGrayBall.h" + +AI_SHADER_NODE_EXPORT_METHODS(apGrayBall) + +enum apGrayBallParams { + p_texture, + p_blur, + p_samples +}; +struct ShaderData +{ + float blur; + int samples; + AtSampler *sampler; +}; + +node_parameters +{ + AiParameterRGB("texture", 0, 0, 0); + AiParameterFlt("blur", 0); + AiParameterInt("samples", 4); +} + +node_initialize +{ + ShaderData *data = (ShaderData *)AiMalloc(sizeof(ShaderData)); + int seed = 0; + data->samples = AiNodeGetInt(node, "samples"); + data->sampler = AiSampler(seed, data->samples, 2); + AiNodeSetLocalData(node, data); +} + +node_update +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + data->blur = AiNodeGetFlt(node, "blur"); + data->samples = AiNodeGetInt(node, "samples"); + int seed = 0; + data->sampler = AiSampler(seed, data->samples, 2); +} + +node_finish +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AiFree(data); +} + +shader_evaluate +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AtVector n = AiV3Normalize(sg->Nf); + AtMatrix matrix; + AiWorldToCameraMatrix(AiUniverseGetCamera(), 1.0, matrix); + n = AiM4VectorByMatrixMult(matrix, n); + + if (data->blur > 0) { + + AtSamplerIterator *iter = AiSamplerIterator(data->sampler, sg); + float samples[2]; + int sample_count = AiSamplerGetSampleCount(iter); + AtRGB color = AI_RGB_BLACK; + + while (AiSamplerGetSample(iter, samples)) { + float u, v; + concentricSampleDisk(samples[0], samples[1], u, v); + sg->u = (n.x + 1.05 + (u * data->blur)) * 0.45; + sg->v = (n.y + 1.05 + (v * data->blur)) * 0.45; + color += AiShaderEvalParamRGB(p_texture); + } + + sg->out.RGB() = color / sample_count; + return; + } + + sg->u = (n.x + 1.05) * 0.45; + sg->v = (n.y + 1.05) * 0.45; + sg->out.RGB() = AiShaderEvalParamRGB(p_texture); + return; +} + +node_loader +{ + if (i > 0) + return false; + + node->methods = apGrayBall; + node->output_type = AI_TYPE_RGBA; + node->name = "apGrayBall"; + node->node_type = AI_NODE_SHADER; + strcpy(node->version, AI_VERSION); + return true; +} \ No newline at end of file diff --git a/src/apGrayBall/apGrayBall.h b/src/apGrayBall/apGrayBall.h new file mode 100644 index 0000000..6953f78 --- /dev/null +++ b/src/apGrayBall/apGrayBall.h @@ -0,0 +1,72 @@ +#include "ai.h" + +// concentricSampleDisk and cosineSampleHemisphere lifted from PBRT +/* +Copyright (c) 1998-2012, Matt Pharr and Greg Humphreys. +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. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"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. +*/ + + +void concentricSampleDisk(float u1, float u2, float& dx, float& dy) +{ + float r, theta; + // Map uniform random numbers to $[-1,1]^2$ + float sx = 2 * u1 - 1; + float sy = 2 * u2 - 1; + + // Map square to $(r,\theta)$ + + // Handle degeneracy at the origin + if (sx == 0.0 && sy == 0.0) { + dx = 0.0; + dy = 0.0; + return; + } + if (sx >= -sy) { + if (sx > sy) { + // Handle first region of disk + r = sx; + if (sy > 0.0) theta = sy / r; + else theta = 8.0f + sy / r; + } + else { + // Handle second region of disk + r = sy; + theta = 2.0f - sx / r; + } + } + else { + if (sx <= sy) { + // Handle third region of disk + r = -sx; + theta = 4.0f - sy / r; + } + else { + // Handle fourth region of disk + r = -sy; + theta = 6.0f + sx / r; + } + } + theta *= float(AI_PI) / 4.f; + dx = r * cosf(theta); + dy = r * sinf(theta); +} \ No newline at end of file diff --git a/src/apGrayBall/apGrayBall.mtd b/src/apGrayBall/apGrayBall.mtd new file mode 100644 index 0000000..a679da6 --- /dev/null +++ b/src/apGrayBall/apGrayBall.mtd @@ -0,0 +1,13 @@ +[node apGrayBall] + maya.name STRING "apGrayBall" + maya.id INT 0x0005105 + maya.classification STRING "shader/surface" + [attr texture] + desc STRING "Gray ball texture" + maya.keyable BOOL false + linkable BOOL true + + [attr blur] + desc STRING "Blur" + maya.keyable BOOL false + linkable BOOL true \ No newline at end of file diff --git a/src/apGrayBall/apGrayBallTemplate.py b/src/apGrayBall/apGrayBallTemplate.py new file mode 100644 index 0000000..15e5b78 --- /dev/null +++ b/src/apGrayBall/apGrayBallTemplate.py @@ -0,0 +1,15 @@ +import maya.mel +from mtoa.ui.ae.shaderTemplate import ShaderAETemplate + +class AEapGrayBallTemplate(ShaderAETemplate): + def setup(self): + self.addSwatch() + self.beginScrollLayout() + self.beginLayout("Textur Attributes", collapse=False) + self.addControl('texture', label='Texture') + self.addControl('blur', label='Blur') + self.endLayout() + maya.mel.eval('AEdependNodeTemplate '+self.nodeName) + self.addExtraControls() + self.endScrollLayout() + \ No newline at end of file diff --git a/src/apHairBSDF/apHairBSDF.cpp b/src/apHairBSDF/apHairBSDF.cpp new file mode 100644 index 0000000..69c0099 --- /dev/null +++ b/src/apHairBSDF/apHairBSDF.cpp @@ -0,0 +1,88 @@ +#include "ai.h" + +AI_SHADER_NODE_EXPORT_METHODS(apHairBSDF) + +enum apHairBSDFParams +{ + p_absorption, + p_r_weight, + p_tt_weight, + p_trt_weight, + p_tangent, + p_roughness, + p_eta, + p_tilt, + p_opacity +}; + + +struct ShaderData +{ + float roughness; + float eta; + float tilt; +}; + +node_parameters +{ + AiParameterRGB("absorption", 0.0, 0.0, 0.0); + AiParameterRGB("R", 0.0, 0.0, 0.0); + AiParameterRGB("TT", 0.0, 0.0, 0.0); + AiParameterRGB("TRT", 0.0, 0.0, 0.0); + AiParameterFlt("roughness", 0); + AiParameterFlt("eta", 0); + AiParameterFlt("tilt", 0); + AiParameterRGB("opacity", 1, 1, 1); +} + +node_initialize +{ + ShaderData *data = (ShaderData *)AiMalloc(sizeof(ShaderData)); + AiNodeSetLocalData(node, data); +} + +node_update +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + data->roughness = AiNodeGetFlt(node, "roughness"); + data->eta = AiNodeGetFlt(node, "eta"); + data->tilt = AiNodeGetFlt(node, "tilt"); + +} + +node_finish +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); +AiFree(data); +} + +shader_evaluate +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AtRGB absorption = AiShaderEvalParamRGB(p_absorption); + AtRGB R_weight = AiShaderEvalParamRGB(p_r_weight); + AtRGB TT_weight = AiShaderEvalParamRGB(p_tt_weight); + AtRGB TRT_weight = AiShaderEvalParamRGB(p_trt_weight); + AtRGB opacity = AiShaderEvalParamRGB(p_opacity); + AtRGB weights[3] = {R_weight, TT_weight, TRT_weight}; + + AtBSDF *bsdf = AidEonBSDF(sg, absorption, weights, sg->dPdv, data->roughness, data->eta, data->tilt); + + AtClosureList closures; + closures.add(bsdf); + closures.add(AiClosureTransparent(sg, 1.0 - opacity)); + sg->out.CLOSURE() = closures; +} + +node_loader +{ + if (i > 0) + return false; + + node->methods = apHairBSDF; + node->output_type = AI_TYPE_CLOSURE; + node->name = "apHairBSDF"; + node->node_type = AI_NODE_SHADER; + strcpy(node->version, AI_VERSION); + return true; +} diff --git a/src/apHairBSDF/apHairBSDF.mtd b/src/apHairBSDF/apHairBSDF.mtd new file mode 100644 index 0000000..3062ba1 --- /dev/null +++ b/src/apHairBSDF/apHairBSDF.mtd @@ -0,0 +1,39 @@ +[node apHairBSDF] + maya.name STRING "apHairBSDF" + maya.id INT 0x0005112 + maya.classification STRING "shader/surface" + + [attr r_weight] + desc STRING "R Weight" + maya.keyable BOOL false + linkable BOOL true + + [attr tt_weight] + desc STRING "TT Weight" + maya.keyable BOOL false + linkable BOOL true + + [attr trt_weight] + desc STRING "TRT Weight" + maya.keyable BOOL false + linkable BOOL true + + [attr roughness] + desc STRING "Specular roughness" + maya.keyable BOOL false + linkable BOOL false + + [attr eta] + desc STRING "Refractive index of hair fiber" + maya.keyable BOOL false + linkable BOOL false + + [attr tilt] + desc STRING "Scale tilt angle" + maya.keyable BOOL false + linkable BOOL false + + [attr opacity] + desc STRING "Opacity" + maya.keyable BOOL false + linkable BOOL true diff --git a/src/apHairBSDF/apHairBSDFTemplate.py b/src/apHairBSDF/apHairBSDFTemplate.py new file mode 100644 index 0000000..f130c24 --- /dev/null +++ b/src/apHairBSDF/apHairBSDFTemplate.py @@ -0,0 +1,20 @@ +import maya.mel +from mtoa.ui.ae.shaderTemplate import ShaderAETemplate + +class AEapHairBSDFTemplate(ShaderAETemplate): + def setup(self): + self.addSwatch() + self.beginScrollLayout() + self.beginLayout("BSDF Attribues", collapse=False) + self.addControl('r_weight', label='R', annotation='Weight of R') + self.addControl('tt_weight', label='TT', annotation='Weight of TT') + self.addControl('trt_weight', label='TRT', annotation='Weight of TRT') + self.addControl('roughness', label='Roughness', annotation='Specular roughness') + self.addControl('eta', label='IOR', annotation='Refractive index of hair fiber') + self.addControl('tilt', label='Tilt', annotation='Scale tilt angle') + self.addControl('opacity', label='Opacity') + self.endLayout() + maya.mel.eval('AEdependNodeTemplate '+self.nodeName) + self.addExtraControls() + self.endScrollLayout() + \ No newline at end of file diff --git a/src/apInteriorMapping/CMakeLists.txt b/src/apInteriorMapping/CMakeLists.txt new file mode 100644 index 0000000..ddf7035 --- /dev/null +++ b/src/apInteriorMapping/CMakeLists.txt @@ -0,0 +1,23 @@ +set(SHADER apInteriorMapping) + +set(SRC_FILES + "apInteriorMapping.cpp") + +set(META_FILES + "apInteriorMapping.mtd") + +set(TEMPLATE_FILES + "apInteriorMappingTemplate.py") + +include_directories(${ARNOLD_INCLUDE_PATH}) +add_library(${SHADER} SHARED ${SRC_FILES}) +set_target_properties(${SHADER} PROPERTIES PREFIX "") + +target_link_libraries(${SHADER} ${ARNOLD_AI_LIBRARY}) + +set(INSTALL_SHADER_TARGET "${CMAKE_INSTALL_PREFIX}/${ARNOLD_VERSION}/${CMAKE_PROJECT_NAME}/shaders") +set(INSTALL_TEMPLATE_TARGET "${CMAKE_INSTALL_PREFIX}/${ARNOLD_VERSION}/${CMAKE_PROJECT_NAME}/templates") + +install(TARGETS ${SHADER} RUNTIME DESTINATION ${INSTALL_SHADER_TARGET}) +install(FILES ${META_FILES} DESTINATION ${INSTALL_SHADER_TARGET}) +install(FILES ${TEMPLATE_FILES} DESTINATION ${INSTALL_TEMPLATE_TARGET}) \ No newline at end of file diff --git a/src/apInteriorMapping/apInteriorMapping.cpp b/src/apInteriorMapping/apInteriorMapping.cpp new file mode 100644 index 0000000..b341b46 --- /dev/null +++ b/src/apInteriorMapping/apInteriorMapping.cpp @@ -0,0 +1,130 @@ +#include "ai.h" +#include + +AI_SHADER_NODE_EXPORT_METHODS(apInteriorMapping) + +enum apInteriorMappingParams +{ + p_ceiling_texture, + p_floor_texture, + p_wall_xy_texture, + p_wall_zy_texture, + p_wall_frequencies, +}; + +inline int step(int step, int value) +{ /*sc*/ + return static_cast(value >= step); +} /*ec*/ + +inline unsigned char step(unsigned char step, unsigned char value) +{ /*sc*/ + return static_cast(value >= step); +} /*ec*/ + +inline float step(float step, float value) +{ /*sc*/ + return static_cast(value >= step); +} + +inline AtVector step(AtVector step, AtVector value) +{ + return AtVector(static_cast(value.x >= step.x), + static_cast(value.y >= step.y), + static_cast(value.z >= step.z)); +} + +inline AtVector floor(AtVector value) +{ + return AtVector(floor(value.x), floor(value.y), floor(value.z)); +} + +struct ShaderData +{ + AtVector wall_frequencies; +}; + +node_parameters +{ + AiParameterRGB("ceiling_texture", 0, 0, 0); + AiParameterRGB("floor_texture", 0, 0, 0); + AiParameterRGB("wall_xy_texture", 0, 0, 0); + AiParameterRGB("wall_zy_texture", 0, 0, 0); + AiParameterVec("wall_frequencies", 1, 1, 1); +} + +node_initialize +{ + ShaderData *data = (ShaderData *)AiMalloc(sizeof(ShaderData)); + AiNodeSetLocalData(node, data); +} + +node_update +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + data->wall_frequencies = AiNodeGetVec(node, "wall_frequencies"); +} + +node_finish +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AiFree(data); +} + +shader_evaluate +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + + AtVector camere_position = AiShaderGlobalsTransformVector(sg, sg->Ro, AI_WORLD_TO_OBJECT); + AtVector position = AiShaderGlobalsTransformVector(sg, sg->P, AI_WORLD_TO_OBJECT); + AtVector direction = position - camere_position; + + //calculate wall locations + AtVector walls = (floor(position * (data->wall_frequencies - 0.1)) + step(AtVector(0, 0, 0), direction)) / (data->wall_frequencies - 0.1); + + //how much of the ray is needed to get from the cameraPosition to each of the walls + AtVector ray_fractions = (walls - camere_position) / direction; + + //texture-coordinates of intersections + AtVector crd = (camere_position + ray_fractions.z * direction); + AtVector2 intersection_xy = 1 * AtVector2(crd.x, crd.y); + AtVector2 intersection_xz = 1 * AtVector2(crd.x, crd.z); + AtVector2 intersection_zy = 1 * AtVector2(crd.z, crd.y); + + //use the intersection as the texture coordinates for the ceiling + sg->u = intersection_xz.x; + sg->v = intersection_xz.y; + AtRGB ceil_colour = AiShaderEvalParamRGB(p_ceiling_texture); + AtRGB floor_colour = AiShaderEvalParamRGB(p_floor_texture); + AtRGB vertical_colour = AiLerp(step(0.0, direction.y), floor_colour, ceil_colour); + + sg->u = intersection_xy.x; + sg->v = intersection_xy.y; + AtRGB wall_xy_colour = AiShaderEvalParamRGB(p_wall_xy_texture); + + sg->u = intersection_zy.x; + sg->v = intersection_zy.y; + AtRGB wall_zy_colour = AiShaderEvalParamRGB(p_wall_zy_texture); + + //choose the closest of these walls for the normal for the lighting + float xVSz = step(ray_fractions.x, ray_fractions.z); + AtRGB interior_colour = AiLerp(xVSz, wall_xy_colour, wall_zy_colour); + float ray_fraction_xVSz = AiLerp(xVSz, ray_fractions.z, ray_fractions.x); + float xzVSy = step(ray_fraction_xVSz, ray_fractions.y); + interior_colour = AiLerp(xzVSy, vertical_colour, interior_colour); + + sg->out.RGB() = interior_colour; +} + +node_loader +{ + if (i > 0) + return false; + + node->methods = apInteriorMapping; + node->output_type = AI_TYPE_RGB; + node->name = "apInteriorMapping"; + node->node_type = AI_NODE_SHADER; + strcpy(node->version, AI_VERSION); + return true; +} diff --git a/src/apInteriorMapping/apInteriorMapping.mtd b/src/apInteriorMapping/apInteriorMapping.mtd new file mode 100644 index 0000000..732c062 --- /dev/null +++ b/src/apInteriorMapping/apInteriorMapping.mtd @@ -0,0 +1,30 @@ +[node apInteriorMapping] + maya.name STRING "apInteriorMapping" + maya.id INT 0x0005114 + maya.classification STRING "shader/texture" + +[attr ceiling_texture] + desc STRING "Ceiling Texture" + maya.keyable BOOL false + linkable BOOL true + +[attr floor_texture] + desc STRING "Floor Texture" + maya.keyable BOOL false + linkable BOOL true + +[attr wall_xy_texture] + desc STRING "Wall XY Texture" + maya.keyable BOOL false + linkable BOOL true + +[attr wall_zy_texture] + desc STRING "Wall YZ Texture" + maya.keyable BOOL false + linkable BOOL true + +[attr wall_frequencies] + desc STRING "Wall Frequencies" + maya.keyable BOOL false + linkable BOOL false + diff --git a/src/apInteriorMapping/apInteriorMappingTemplate.py b/src/apInteriorMapping/apInteriorMappingTemplate.py new file mode 100644 index 0000000..536ad1e --- /dev/null +++ b/src/apInteriorMapping/apInteriorMappingTemplate.py @@ -0,0 +1,21 @@ +import maya.mel +from mtoa.ui.ae.shaderTemplate import ShaderAETemplate + +class AEapInteriorMappingTemplate(ShaderAETemplate): + def setup(self): + self.addSwatch() + self.beginScrollLayout() + + self.beginLayout("Texture Attribues", collapse=False) + self.addControl('ceiling_texture', label='Ceiling Texture', annotation='Ceiling Texture') + self.addControl('floor_texture', label='Floor Texture', annotation='Floor Texture') + self.addControl('wall_xy_texture', label='Wall XY Texture', annotation='Wall XY Texture') + self.addControl('wall_zy_texture', label='Wall ZY Texture', annotation='Wall ZY Texture') + self.addControl('wall_frequencies', label='Wall Frequencies', annotation='Wall Frequencies') + self.endLayout() + + maya.mel.eval('AEdependNodeTemplate '+self.nodeName) + + self.addExtraControls() + self.endScrollLayout() + diff --git a/src/apIrradianceCache/apIrradianceCache.cpp b/src/apIrradianceCache/apIrradianceCache.cpp new file mode 100644 index 0000000..de59f41 --- /dev/null +++ b/src/apIrradianceCache/apIrradianceCache.cpp @@ -0,0 +1,74 @@ +#include "octree.h" + +#include + +AI_SHADER_NODE_EXPORT_METHODS(apIrradianceCache) + +enum apIrradianceCacheParams +{ + p_passthough, + +}; + +struct IrradianceCacheData +{ + AtRGB color; + AtVector normal; +}; + +struct ShaderData +{ + Octree octree; +}; + +node_parameters +{ + AiParameterClosure("passthough"); +} + +node_initialize +{ + ShaderData *data = (ShaderData *)AiMalloc(sizeof(ShaderData)); + AtNode *options = AiUniverseGetOptions(); + int xres = AiNodeGetInt(options, "xres"); + int yres = AiNodeGetInt(options, "yres"); + data->octree = Octree(xres * yres); + AiNodeSetLocalData(node, data); +} + +node_update +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); +} + +node_finish +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AiFree(data); +} + +shader_evaluate +{ + AiShaderEvalParamClosure(p_passthough); + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + + int i = sg->x + sg->y; + AtRGB irr = AiIrradiance(sg->P, sg->N, sg->tid, i); + IrradianceCacheData irrCache; + irrCache.color = irr; + irrCache.normal = sg->N; + data->octree.set(sg->P.x, sg->P.y, sg->P.z, irrCache); +} + +node_loader +{ + if (i > 0) + return false; + + node->methods = apIrradianceCache; + node->output_type = AI_TYPE_RGB; + node->name = "apIrradianceCache"; + node->node_type = AI_NODE_SHADER; + strcpy(node->version, AI_VERSION); + return true; +} \ No newline at end of file diff --git a/src/apIrradianceCache/array.h b/src/apIrradianceCache/array.h new file mode 100644 index 0000000..d27a8ec --- /dev/null +++ b/src/apIrradianceCache/array.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2007 Simon Perreault + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef ARRAY_H +#define ARRAY_H + +#include "shareddata.h" +#include "tinyvector.h" + +template< typename T, int N > +class Array +{ +public: + Array(); + Array( const TinyVector& sizes ); + + const TinyVector& sizes() const; + + const T& at( const TinyVector& indices ) const; + const T& operator() ( const TinyVector& indices ) const; + T& operator() ( const TinyVector& indices ); + + Array subarray( const TinyVector& begin, + const TinyVector& end ); + +private: + int dataIndex( const TinyVector& indices ) const; + +private: + SharedData data_; + int offset_; + TinyVector strides_; + TinyVector sizes_; +}; + +template< typename T, int N > +Array::Array() + : data_(0) + , sizes_(0) +{ +} + +template< typename T, int N > +Array::Array( const TinyVector& sizes ) + : data_( new T[prod(sizes)] ) + , offset_(0) + , strides_( cumprod(sizes)/sizes(0) ) + , sizes_(sizes) +{ +} + +template< typename T, int N > +const TinyVector& Array::sizes() const +{ + return sizes_; +} + +template< typename T, int N > +const T& Array::at( const TinyVector& indices ) const +{ + return data_[ dataIndex(indices) ]; +} + +template< typename T, int N > +const T& Array::operator() ( const TinyVector& indices ) const +{ + return at(indices); +} + +template< typename T, int N > +T& Array::operator() ( const TinyVector& indices ) +{ + return data_[ dataIndex(indices) ]; +} + +template< typename T, int N > +int Array::dataIndex( const TinyVector& indices ) const +{ + for ( int i = 0; i < N; ++i ) { + assert( indices(i) >= 0 && indices(i) < sizes_(i) ); + } + + return offset_ + sum( indices * strides_ ); +} + +template< typename T, int N > +Array Array::subarray( const TinyVector& begin, + const TinyVector& end ) +{ + Array sub; + sub.data_ = data_; + sub.offset_ = dataIndex(begin); + sub.strides_ = strides_; + sub.sizes_ = end - begin; + return sub; +} + +#endif diff --git a/src/apIrradianceCache/array2d.h b/src/apIrradianceCache/array2d.h new file mode 100644 index 0000000..d5a62fb --- /dev/null +++ b/src/apIrradianceCache/array2d.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2007 Simon Perreault + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef ARRAY2D_H +#define ARRAY2D_H + +#include "array.h" + +template< typename T > +class Array2D : public Array +{ +public: + Array2D(); + Array2D( int m, int n ); + Array2D( const Array& array ); + + int M() const; + int N() const; + + const T& at( int i, int j ) const; + const T& operator() ( int i, int j ) const; + T& operator() ( int i, int j ); + + Array2D subarray( int iBegin, int jBegin, int iEnd, int jEnd ); +}; + +template< typename T > +Array2D::Array2D() + : Array() +{ +} + +template< typename T > +Array2D::Array2D( int m, int n ) + : Array() +{ + TinyVector sizes; + sizes(1) = m; + sizes(0) = n; + + Array::operator= ( Array(sizes) ); +} + +template< typename T > +Array2D::Array2D( const Array& array ) + : Array(array) +{ +} + +template< typename T > +int Array2D::M() const +{ + return this->sizes()(1); +} + +template< typename T > +int Array2D::N() const +{ + return this->sizes()(0); +} + +template< typename T > +const T& Array2D::at( int i, int j ) const +{ + TinyVector indices; + indices(1) = i; + indices(0) = j; + return Array::at(indices); +} + +template< typename T > +const T& Array2D::operator() ( int i, int j ) const +{ + return at(i,j); +} + +template< typename T > +T& Array2D::operator() ( int i, int j ) +{ + TinyVector indices; + indices(1) = i; + indices(0) = j; + return Array::operator()(indices); +} + +template< typename T > +Array2D Array2D::subarray( int iBegin, int jBegin, int iEnd, int jEnd ) +{ + TinyVector begin, end; + begin(1) = iBegin; + begin(0) = jBegin; + end(1) = iEnd; + end(0) = jEnd; + return Array::subarray( begin, end ); +} + +#endif diff --git a/src/apIrradianceCache/numtraits.h b/src/apIrradianceCache/numtraits.h new file mode 100644 index 0000000..72873a6 --- /dev/null +++ b/src/apIrradianceCache/numtraits.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2007 Simon Perreault + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef NUMTRAITS_H +#define NUMTRAITS_H + +template< typename T1, typename T2 > +class BinaryNumericTraits +{ +public: + typedef T1 OpResult; +}; + +template<> +class BinaryNumericTraits +{ +public: + typedef double OpResult; +}; + +template<> +class BinaryNumericTraits +{ +public: + typedef double OpResult; +}; + +#endif diff --git a/src/apIrradianceCache/octree.h b/src/apIrradianceCache/octree.h new file mode 100644 index 0000000..930c648 --- /dev/null +++ b/src/apIrradianceCache/octree.h @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2007 Simon Perreault + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef OCTREE_H +#define OCTREE_H + +#include "array2d.h" +#include "point3d.h" + +#include +#include +#include +#include + +template< typename T, int AS = 1 > +class Octree +{ +public: + Octree( int size, const T& emptyValue = T(0) ); + Octree( const Octree& o ); + ~Octree(); + + // Accessors + int size() const; + const T& emptyValue() const; + + static unsigned long branchBytes(); + static unsigned long aggregateBytes(); + static unsigned long leafBytes(); + unsigned long bytes() const; + + int nodes() const; + int nodesAtSize( int size ) const; + + // Mutators + void setEmptyValue( const T& emptyValue ); + + void swap( Octree& o ); + Octree& operator= ( Octree o ); + + // Indexing operators + T& operator() ( int x, int y, int z ); + const T& operator() ( int x, int y, int z ) const; + const T& at( int x, int y, int z ) const; + + void set( int x, int y, int z, const T& value ); + void erase( int x, int y, int z ); + + Array2D zSlice( int z ) const; + + // I/O functions + void writeBinary( std::ostream& out ) const; + void readBinary( std::istream& in ); + +protected: + + // Octree node types + class Node; + class Branch; + class Aggregate; + class Leaf; + enum NodeType { BranchNode, AggregateNode, LeafNode }; + + Node*& root(); + const Node* root() const; + + static void deleteNode( Node** node ); + +private: + // Recursive helper functions + void eraseRecursive( Node** node, int size, int x, int y, int z ); + static unsigned long bytesRecursive( const Node* node ); + static int nodesRecursive( const Node* node ); + static int nodesAtSizeRecursive( int targetSize, int size, Node* node ); + void zSliceRecursive( Array2D slice, const Node* node, int size, + int x, int y, int z, int targetZ ) const; + static void writeBinaryRecursive( std::ostream& out, const Node* node ); + static void readBinaryRecursive( std::istream& in, Node** node ); + +protected: + // Node classes + + class Node + { + public: + NodeType type() const; + + protected: + Node( NodeType type ); + ~Node() {}; + + private: + NodeType type_ : 2; + }; + + class Branch : public Node + { + public: + Branch(); + Branch( const Branch& b ); + ~Branch(); + + const Node* child( int x, int y, int z ) const; + Node*& child( int x, int y, int z ); + const Node* child( int index ) const; + Node*& child( int index ); + + friend void Octree::deleteNode( Node** node ); + + private: + Branch& operator= ( Branch b ); + + private: + Node* children[2][2][2]; + }; + + class Aggregate : public Node + { + public: + Aggregate( const T& v ); + + const T& value( int x, int y, int z ) const; + T& value( int x, int y, int z ); + void setValue( int x, int y, int z, const T& v ); + + const T& value( int i ) const; + T& value( int i ); + void setValue( int i, const T& v ); + + friend void Octree::deleteNode( Node** node ); + + private: + ~Aggregate() {}; + + private: + T value_[AS][AS][AS]; + }; + + class Leaf : public Node + { + public: + Leaf( const T& v ); + + const T& value() const; + T& value(); + void setValue( const T& v ); + + friend void Octree::deleteNode( Node** node ); + + private: + ~Leaf() {}; + + private: + T value_; + }; + + static const int aggregateSize_ = AS; + +private: + Node* root_; + T emptyValue_; + int size_; +}; + +#include "octree.tcc" + +#endif diff --git a/src/apIrradianceCache/octree.tcc b/src/apIrradianceCache/octree.tcc new file mode 100644 index 0000000..ceb87a1 --- /dev/null +++ b/src/apIrradianceCache/octree.tcc @@ -0,0 +1,955 @@ +/* + * Copyright (C) 2007 Simon Perreault + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +/** + * \class Octree + * \brief Generic octree template + * + * \author Simon Perreault + * \date April 2007 + * + * This class template represents an octree, often used for manipulating 3-D + * scattered data efficiently. The type of the contained data is supplied as a + * template parameter. + * + * \param T Type of the contained data. Requirements on type: must be copyable + * and default-constructible. + * + * \param AS Short for "aggregate size." As an optimization, leaves can be + * aggregated so that the relative size of pointers is diminished. This is 1 by + * default, but should be set higher when the size of \a T is small. Must be + * a power of two. + */ + +/** + * \param size Size of octree, in nodes. Should be a power of two. For example, + * an octree with \a size = 256 will represent a cube divided into 256x256x256 + * nodes. Must be a power of two. + * + * \param emptyValue This is the value that will be returned when accessing + * regions of the 3-D volume where no node has been allocated. In other words, + * instead of following a null node pointer, this value is returned. Since the + * octree root is initially a null pointer, the whole volume is initialized to + * this value. + */ +template< typename T, int AS > +Octree::Octree( int size, const T& emptyValue ) + : root_(0) + , emptyValue_(emptyValue) + , size_(size) +{ + // Make sure size is power of two. + assert( ((size - 1) & size) == 0 ); + assert( ((AS - 1) & AS) == 0 ); +} + +/** + * Performs a deep copy of an octree. All branch pointers will be followed + * recursively and new nodes will be allocated. + * + * \param o Octree to be copied. + */ +template< typename T, int AS > +Octree::Octree( const Octree& o ) + : emptyValue_( o.emptyValue_ ) + , size_( o.size_ ) +{ + if ( !o.root_ ) { + root_ = 0; + } else { + switch ( o.root_->type() ) { + case BranchNode: + root_ = new Branch ( *reinterpret_cast(o.root_) ); + break; + case LeafNode: + root_ = new Leaf ( *reinterpret_cast(o.root_) ); + break; + case AggregateNode: + root_ = new Aggregate( *reinterpret_cast(o.root_) ); + break; + } + } +} + +/** + * Recursively deletes all nodes by following branch pointers. + */ +template< typename T, int AS > +Octree::~Octree() +{ + deleteNode(&root_); +} + +/** + * Swaps the octree's contents with another's. This is a cheap operation as only + * the root pointers are swapped, not the whole structure. + */ +template< typename T, int AS > +void Octree::swap( Octree& o ) +{ + std::swap( emptyValue_, o.emptyValue_ ); // This can throw. + + // These can't. + std::swap( root_, o.root_ ); + std::swap( size_, o.size_ ); +} + +/** + * Assigns to this octree the contents of octree \a o. + */ +template< typename T, int AS > +Octree& Octree::operator= ( Octree o ) +{ + swap(o); + return *this; +} + +/** + * \return Size of octree, in nodes, as specified in the constructor. + */ +template< typename T, int AS > +int Octree::size() const +{ + return size_; +} + +/** + * \return Value of empty nodes, as specified in the constructor. + * \see setEmptyValue() + */ +template< typename T, int AS > +const T& Octree::emptyValue() const +{ + return emptyValue_; +} + +/** + * Sets the value of empty nodes to \a emptyValue. + * \see setEmptyValue() + */ +template< typename T, int AS > +void Octree::setEmptyValue( const T& emptyValue ) +{ + emptyValue_ = emptyValue; +} + +/** + * Deletes a node polymorphically. If the node is a branch node, it will delete + * all its subtree recursively. + */ +template< typename T, int AS > +void Octree::deleteNode( Node** node ) +{ + assert(node); + if (*node) { + if ( (*node)->type() == BranchNode ) { + delete reinterpret_cast(*node); + } + else if ( (*node)->type() == AggregateNode ) { + delete reinterpret_cast(*node); + } + else { + assert( (*node)->type() == LeafNode ); + delete reinterpret_cast(*node); + } + *node = 0; + } +} + +/** + * \return Pointer to octree's root node. + */ +template< typename T, int AS > +typename Octree::Node*& Octree::root() +{ + return root_; +} + +/** + * Const version of above. + */ +template< typename T, int AS > +const typename Octree::Node* Octree::root() const +{ + return root_; +} + +/** + * \return Value at index (\a x,\a y,\a z). If no node exists at this index, the + * value returned by emptyValue() is returned. + * + * \remarks Memory access is faster when \a x varies the quickest, followed by + * \a y and then by \a z. Therefore you should write nested loops in this order + * for faster access: + * + * \code + * for ( int z = 0; z < ...; ++z ) { + * for ( int y = 0; y < ...; ++y ) { + * for ( int x = 0; x < ...; ++x ) { + * ... = octree.at(x,y,z); + * } + * } + * } + * \endcode + * + * However, zSlice() provides an even faster way. + */ +template< typename T, int AS > +const T& Octree::at( int x, int y, int z ) const +{ + assert( x >= 0 && x < size_ ); + assert( y >= 0 && y < size_ ); + assert( z >= 0 && z < size_ ); + + Node* n = root_; + int size = size_; + + while ( size != aggregateSize_ ) { + if (!n) { + return emptyValue_; + } + else if ( n->type() == BranchNode ) { + size /= 2; + n = reinterpret_cast(n)->child( + !!(x & size), !!(y & size), !!(z & size) ); + } + else { + assert( n->type() == LeafNode ); + return reinterpret_cast(n)->value(); + } + } + + if (!n) { + return emptyValue_; + } + + --size; + return reinterpret_cast(n)->value( + x & size, y & size, z & size ); +} + +/** + * Synonym of at(). + */ +template< typename T, int AS > +const T& Octree::operator() ( int x, int y, int z ) const +{ + return at(x,y,z); +} + +/** + * \return Reference to value at index (\a x,\a y,\a z). If no node exists at + * this index, a new one is created (along with the necessary ancestry), + * initialized to the value returned by emptyValue(), and returned. + * + * \remarks Be careful when calling this function. If you do not want to + * inadvertently create new nodes, use the at() function. + * + * \see at() + */ +template< typename T, int AS > +T& Octree::operator() ( int x, int y, int z ) +{ + assert( x >= 0 && x < size_ ); + assert( y >= 0 && y < size_ ); + assert( z >= 0 && z < size_ ); + + Node** n = &root_; + int size = size_; + + while ( size != aggregateSize_ ) { + if (!*n) { + *n = new Branch; + } + else if ( (*n)->type() == BranchNode ) { + size /= 2; + n = &reinterpret_cast(*n)->child( + !!(x & size), !!(y & size), !!(z & size) ); + } + else { + return reinterpret_cast(*n)->value(); + } + } + + if (!*n) { + *n = new Aggregate(emptyValue_); + } + + --size; + return reinterpret_cast(*n)->value( + x & size, y & size, z & size ); +} + +/** + * Sets the value of the node at (\a x, \a y, \a z) to \a value. If \a value is + * the empty value, the node is erased. Otherwise, the node is created if it did + * not already exist and its value is set to \a value. + */ +template< typename T, int AS > +void Octree::set( int x, int y, int z, const T& value ) +{ + if ( value != emptyValue() ) { + (*this)(x,y,z) = value; + } + else { + erase(x,y,z); + } +} + +/** + * Erases the node at index (\a x,\a y,\a z). After the call, + * at(x,y,z) will return the value returned by emptyValue(). + * + * This function will free as much memory as possible. For example, when erasing + * the single child of a branch node, the branch node itself will be erased and + * replaced by a null pointer in its parent. This will percolate to the top of + * the tree if necessary. + */ +template< typename T, int AS > +void Octree::erase( int x, int y, int z ) +{ + assert( x >= 0 && x < size_ ); + assert( y >= 0 && y < size_ ); + assert( z >= 0 && z < size_ ); + + eraseRecursive( &root_, size_, x, y, z ); +} + +/** + * Helper function for erase() method. + */ +template< typename T, int AS > +void Octree::eraseRecursive( Node** node, int size, int x, int y, int z ) +{ + assert(node); + + if ( !*node ) { + return; + } + + if ( size != aggregateSize_ ) { + if ( (*node)->type() == BranchNode ) { + size /= 2; + Branch* b = reinterpret_cast(*node); + eraseRecursive( &b->child(!!(x & size), !!(y & size), !!(z & size)), + size, x, y, z ); + + for ( int i = 0; i < 8; ++i ) { + if ( b->child(i) ) { + return; + } + } + deleteNode(node); + } + else if ( reinterpret_cast(*node)->value() == emptyValue_ ) { + deleteNode(node); + } + else { + Branch* b = new Branch; + size /= 2; + int childIndex = ( x & size ? 1 : 0 ) + | ( y & size ? 2 : 0 ) + | ( z & size ? 4 : 0 ); + const T& value = reinterpret_cast(*node)->value(); + try { + for ( int i = 0; i < 8; ++i ) { + if ( i == childIndex ) { + continue; + } + if ( size == aggregateSize_ ) { + b->child(i) = new Leaf(value); + } + else { + b->child(i) = new Aggregate(value); + } + } + } + catch (...) { + Node* bb = b; + deleteNode(&bb); + throw; + } + + deleteNode(node); + *node = b; + node = &b->child(childIndex); + } + } + else { + --size; + Aggregate* a = reinterpret_cast(*node); + a->setValue( x & size, y & size, z & size, emptyValue_ ); + + for ( int i = 0; i < AS*AS*AS; ++i ) { + if ( a->value(i) != emptyValue_ ) { + return; + } + } + deleteNode(node); + } +} + +/** + * \return Number of bytes a branch node occupies. + */ +template< typename T, int AS > +unsigned long Octree::branchBytes() +{ + return sizeof(Branch); +} + +/** + * \return Number of bytes an aggregate node occupies. + */ +template< typename T, int AS > +unsigned long Octree::aggregateBytes() +{ + return sizeof(Aggregate); +} + +/** + * \return Number of bytes a leaf node occupies. + */ +template< typename T, int AS > +unsigned long Octree::leafBytes() +{ + return sizeof(Leaf); +} + +/** + * \return Total number of nodes in the octree. + */ +template< typename T, int AS > +int Octree::nodes() const +{ + return nodesRecursive(root_); +} + +/** + * Helper function for nodes() method. + */ +template< typename T, int AS > +int Octree::nodesRecursive( const Node* node ) +{ + if ( !node ) { + return 0; + } + + int n = 1; + if ( node->type() == BranchNode ) { + for ( int i = 0; i < 8; ++i ) { + n += nodesRecursive( + reinterpret_cast(node)->child(i) ); + } + } + + return n; +} + +/** + * \return Total number of bytes the octree occupies. + * + * \remarks Memory fragmentation may make the actual memory usage significantly + * higher. + */ +template< typename T, int AS > +unsigned long Octree::bytes() const +{ + return bytesRecursive(root_) + sizeof(*this); +} + +/** + * Helper function for bytes() method. + */ +template< typename T, int AS > +unsigned long Octree::bytesRecursive( const Node* node ) +{ + if ( !node ) { + return 0; + } + + unsigned long b = 0; + switch ( node->type() ) { + case BranchNode: + b = sizeof(Branch); + for ( int i = 0; i < 8; ++i ) { + b += bytesRecursive( + reinterpret_cast(node)->child(i) ); + } + break; + + case LeafNode: + b = sizeof(Leaf); + break; + + case AggregateNode: + b = sizeof(Aggregate); + break; + } + + return b; +} + +/** + * \return Number of nodes of at size \a size. For example, the root (if + * allocated) is the single node of size 1. At size n there may be a + * maximum of 2n nodes. + * + * For sizes lower than the aggregate size, this function will always return + * zero. + */ +template< typename T, int AS > +int Octree::nodesAtSize( int size ) const +{ + return nodesAtSizeRecursive( size, size_, root_ ); +} + +/** + * Helper function for nodesAtSize() method. + */ +template< typename T, int AS > +int Octree::nodesAtSizeRecursive( int targetSize, int size, Node* node ) +{ + if (node) { + if ( size == targetSize ) { + return 1; + } + + if ( node->type() == BranchNode ) { + int sum = 0; + for ( int i = 0; i < 2; ++i ) { + for ( int j = 0; j < 2; ++j ) { + for ( int k = 0; k < 2; ++k ) { + sum += nodesAtSizeRecursive( targetSize, size/2, + reinterpret_cast(node)->child(k,j,i) ); + } + } + } + return sum; + } + } + + return 0; +} + +template< typename T, int AS > +Octree::Node::Node( NodeType type ) + : type_(type) +{ +} + +template< typename T, int AS > +typename Octree::NodeType Octree::Node::type() const +{ + return type_; +} + +template< typename T, int AS > +Octree::Branch::Branch() + : Node(BranchNode) +{ + memset( children, 0, sizeof(children) ); +} + +template< typename T, int AS > +Octree::Branch::Branch( const Branch& b ) + : Node(BranchNode) +{ + for ( int i = 0; i < 8; ++i ) { + if ( b.child(i) ) { + switch ( b.child(i)->type() ) { + case BranchNode: + child(i) = new Branch( + *reinterpret_cast(b.child(i)) ); + break; + case LeafNode: + child(i) = new Leaf( + *reinterpret_cast(b.child(i)) ); + break; + case AggregateNode: + child(i) = new Aggregate( + *reinterpret_cast(b.child(i)) ); + break; + } + } + else { + child(i) = 0; + } + } +} + +template< typename T, int AS > +Octree::Branch::~Branch() +{ + for ( int i = 0; i < 2; ++i ) { + for ( int j = 0; j < 2; ++j ) { + for ( int k = 0; k < 2; ++k ) { + assert( children[i][j][k] != this ); + deleteNode( &children[i][j][k] ); + } + } + } +} + +template< typename T, int AS > +const typename Octree::Node* Octree::Branch::child( + int x, int y, int z ) const +{ + assert( x == 0 || x == 1 ); + assert( y == 0 || y == 1 ); + assert( z == 0 || z == 1 ); + return children[z][y][x]; +} + +template< typename T, int AS > +typename Octree::Node*& Octree::Branch::child( int x, int y, int z ) +{ + assert( x == 0 || x == 1 ); + assert( y == 0 || y == 1 ); + assert( z == 0 || z == 1 ); + return children[z][y][x]; +} + +template< typename T, int AS > +const typename Octree::Node* Octree::Branch::child( int index ) + const +{ + assert( index >= 0 && index < 8 ); + return *( &children[0][0][0] + index ); +} + +template< typename T, int AS > +typename Octree::Node*& Octree::Branch::child( int index ) +{ + assert( index >= 0 && index < 8 ); + return *( &children[0][0][0] + index ); +} + +template< typename T, int AS > +Octree::Aggregate::Aggregate( const T& v ) + : Node(AggregateNode) +{ + for ( int i = 0; i < AS; ++i ) { + for ( int j = 0; j < AS; ++j ) { + for ( int k = 0; k < AS; ++k ) { + value_[i][j][k] = v; + } + } + } +} + +template< typename T, int AS > +const T& Octree::Aggregate::value( int x, int y, int z ) const +{ + assert( x >= 0 && x < AS ); + assert( y >= 0 && y < AS ); + assert( z >= 0 && z < AS ); + + return value_[z][y][x]; +} + +template< typename T, int AS > +T& Octree::Aggregate::value( int x, int y, int z ) +{ + assert( x >= 0 && x < AS ); + assert( y >= 0 && y < AS ); + assert( z >= 0 && z < AS ); + + return value_[z][y][x]; +} + +template< typename T, int AS > +void Octree::Aggregate::setValue( int x, int y, int z, const T& v ) +{ + assert( x >= 0 && x < AS ); + assert( y >= 0 && y < AS ); + assert( z >= 0 && z < AS ); + + value_[z][y][x] = v; +} + +template< typename T, int AS > +const T& Octree::Aggregate::value( int i ) const +{ + assert( i >= 0 && i < AS*AS*AS ); + + return *( &value_[0][0][0] + i ); +} + +template< typename T, int AS > +T& Octree::Aggregate::value( int i ) +{ + assert( i >= 0 && i < AS*AS*AS ); + + return *( &value_[0][0][0] + i ); +} + +template< typename T, int AS > +void Octree::Aggregate::setValue( int i, const T& v ) +{ + assert( i >= 0 && i < AS*AS*AS ); + + *( &value_[0][0][0] + i ) = v; +} + +template< typename T, int AS > +Octree::Leaf::Leaf( const T& v ) + : Node(LeafNode) + , value_(v) +{ +} + +template< typename T, int AS > +const T& Octree::Leaf::value() const +{ + return value_; +} + +template< typename T, int AS > +T& Octree::Leaf::value() +{ + return value_; +} + +template< typename T, int AS > +void Octree::Leaf::setValue( const T& v ) +{ + value_ = v; +} + +/** + * \return A slice of the octree, perpendicular to the Z axis. The content of + * all nodes for which the Z index is \a z will be copied into the returned + * array. If no node exists for a given index, the value returned by + * emptyValue() will be written instead. + * + * \remarks This method ought to be relatively fast as long the the time + * required to copy values does not dwarf the time for indexing into the octree + * (this should be the case for built-in C++ types such as int and double). + * As a result, using this function is an easy way to accelerate the infamous + * three-level nested loops. For example: + * + * \code + * for ( int z = 0; z < ...; ++z ) { + * tmp = octree.zSlice(z); + * for ( int y = 0; y < ...; ++y ) { + * for ( int x = 0; x < ...; ++x ) { + * ... = tmp(y,x); + * } + * } + * } + * \endcode + */ +template< typename T, int AS > +Array2D Octree::zSlice( int z ) const +{ + assert( z >= 0 && z < size_ ); + + Array2D slice( size_, size_ ); + zSliceRecursive( slice, root_, size_, 0, 0, 0, z ); + + return slice; +} + +/** + * Helper function for zSlice() method. + */ +template< typename T, int AS > +void Octree::zSliceRecursive( Array2D slice, const Node* node, + int size, int x, int y, int z, int targetZ ) const +{ + if (!node) { + for ( int i = 0; i < slice.M(); ++i ) { + for ( int j = 0; j < slice.N(); ++j ) { + slice(i,j) = emptyValue_; + } + } + } + else if ( node->type() == BranchNode ) { + size /= 2; + for ( int i = 0; i < 2; ++i ) { + for ( int j = 0; j < 2; ++j ) { + zSliceRecursive( slice.subarray( i*size, j*size, + (i+1)*size, (j+1)*size), + reinterpret_cast(node)->child( + j, i, !!(targetZ & size)), + size, x, y, z, targetZ ); + } + } + } + else if ( node->type() == AggregateNode ) { + for ( int i = 0; i < slice.M(); ++i ) { + for ( int j = 0; j < slice.N(); ++j ) { + slice(i,j) = reinterpret_cast(node)->value( + j, i, targetZ - z & (size-1) ); + } + } + } + else { + assert( node->type() == LeafNode ); + for ( int i = 0; i < slice.M(); ++i ) { + for ( int j = 0; j < slice.N(); ++j ) { + slice(i,j) = reinterpret_cast(node)->value(); + } + } + } +} + +/** + * Writes the octree in binary form to the output stream \a out. This should be + * fast, but note that the type \a T will be written as it appears in memory. + * That is, if it is a complex type containing pointers, the pointer addresses + * will be written instead of the data pointed at. For complex types, you should + * roll your own function. + */ +template< typename T, int AS > +void Octree::writeBinary( std::ostream& out ) const +{ + if ( !root_ ) { + static const char zero = 0; + out.write( &zero, 1 ); + } + else { + static const char one = 1; + out.write( &one, 1 ); + + writeBinaryRecursive( out, root() ); + } + + out.write( reinterpret_cast(&emptyValue_), sizeof(T) ); + out.write( reinterpret_cast(&size_), sizeof(int) ); +} + +template< typename T, int AS > +void Octree::writeBinaryRecursive( std::ostream& out, const Node* node ) +{ + assert(node); + + if ( !out.good() ) { + return; + } + + char type = node->type(); + out.write( &type, 1 ); + + switch (type) { + case BranchNode: + { + const Branch* b = reinterpret_cast(node); + + char children = 0; + for ( int i = 0; i < 8; ++i ) { + children |= ( b->child(i) != 0 ) << i; + } + out.write( &children, 1 ); + + for ( int i = 0; i < 8; ++i ) { + if ( b->child(i) ) { + writeBinaryRecursive( out, b->child(i) ); + } + } + } + break; + + case AggregateNode: + out.write( reinterpret_cast( + &reinterpret_cast(node)->value(0,0,0) + ), + AS*AS*AS*sizeof(T) ); + break; + + case LeafNode: + out.write( reinterpret_cast( + &reinterpret_cast(node)->value() + ), + sizeof(T) ); + break; + } +} + +/** + * Reads the octree from \a in. It must previously have been written using + * writeBinary(). + */ +template< typename T, int AS > +void Octree::readBinary( std::istream& in ) +{ + Octree tmp(0); + + char root; + in.read( &root, 1 ); + if (root) { + readBinaryRecursive( in, &tmp.root_ ); + } + + in.read( reinterpret_cast(&tmp.emptyValue_), sizeof(T) ); + in.read( reinterpret_cast(&tmp.size_), sizeof(int) ); + + if ( in.good() ) { + swap(tmp); + } +} + +template< typename T, int AS > +void Octree::readBinaryRecursive( std::istream& in, Node** node ) +{ + assert(node); + + if ( !in.good() ) { + return; + } + + char type; + in.read( &type, 1 ); + + switch (type) { + case BranchNode: + { + Branch* b = new Branch; + *node = b; + + char children; + in.read( &children, 1 ); + + for ( int i = 0; i < 8; ++i ) { + if ( children & (1 << i) ) { + readBinaryRecursive( in, &b->child(i) ); + } + } + } + break; + + case AggregateNode: + { + Aggregate* a = new Aggregate( T(0) ); + *node = a; + in.read( reinterpret_cast(&a->value(0,0,0)), + AS*AS*AS*sizeof(T) ); + } + break; + + case LeafNode: + { + Leaf* l = new Leaf( T(0) ); + *node = l; + in.read( reinterpret_cast(&l->value()), sizeof(T) ); + } + break; + } +} diff --git a/src/apIrradianceCache/point3d.h b/src/apIrradianceCache/point3d.h new file mode 100644 index 0000000..7cb400f --- /dev/null +++ b/src/apIrradianceCache/point3d.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2007 Simon Perreault + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef POINT3D_H +#define POINT3D_H + +#include "tinyvector.h" + +template< typename T > +class Point3D : public TinyVector +{ +public: + Point3D() {} + + Point3D( T x, T y, T z ) + { + (*this)(0) = x; + (*this)(1) = y; + (*this)(2) = z; + } + + Point3D( const TinyVector& v ) + : TinyVector(v) + { + } + + const T& x() const { return this->at(0); } + const T& y() const { return this->at(1); } + const T& z() const { return this->at(2); } + T& x() { return (*this)(0); } + T& y() { return (*this)(1); } + T& z() { return (*this)(2); } +}; + +#endif diff --git a/src/apIrradianceCache/shareddata.h b/src/apIrradianceCache/shareddata.h new file mode 100644 index 0000000..49296ca --- /dev/null +++ b/src/apIrradianceCache/shareddata.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2007 Simon Perreault + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SHAREDDATA_H +#define SHAREDDATA_H + +#include + +/** + * \warning This class isn't thread-safe! In particular, we should use atomic + * operations when incrementing or decrementing the reference count. See Boost's + * shared_ptr for an alternative. + */ +template< typename T > +class SharedData +{ +public: + SharedData( T* data = 0 ); + SharedData( const SharedData& sharedData ); + ~SharedData(); + + void swap( SharedData& sharedData ); + SharedData& operator= ( SharedData sharedData ); + + T& operator[] ( int i ) const; + +private: + T* data_; + int* refcount_; +}; + +template< typename T > +SharedData::SharedData( T* data ) + : data_(data) +{ + try { + refcount_ = new int(1); + } + catch (...) { + delete[] data_; + throw; + } +} + +template< typename T > +SharedData::SharedData( const SharedData& sharedData ) + : data_( sharedData.data_ ) + , refcount_( sharedData.refcount_ ) +{ + ++*refcount_; +} + +template< typename T > +SharedData::~SharedData() +{ + if ( --*refcount_ == 0 ) { + delete[] data_; + delete refcount_; + } +} + +template< typename T > +void SharedData::swap( SharedData& sharedData ) +{ + std::swap( sharedData.data_, data_ ); + std::swap( sharedData.refcount_, refcount_ ); +} + +template< typename T > +SharedData& SharedData::operator= ( SharedData sharedData ) +{ + swap(sharedData); + return *this; +} + +template< typename T > +T& SharedData::operator[] ( int i ) const +{ + assert(data_); + return data_[i]; +} + +#endif diff --git a/src/apIrradianceCache/tinyvector.h b/src/apIrradianceCache/tinyvector.h new file mode 100644 index 0000000..cf5fc81 --- /dev/null +++ b/src/apIrradianceCache/tinyvector.h @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2007 Simon Perreault + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef TINYVECTOR_H +#define TINYVECTOR_H + +#include "numtraits.h" + +template< typename T, int N > +class TinyVector +{ +public: + TinyVector(); + TinyVector( const T& value ); + + template< typename T2 > + TinyVector( const TinyVector& v ); + + template< typename T2 > + TinyVector& operator= ( const TinyVector& v ); + + const T& at( int i ) const { return data_[i]; } + const T& operator() ( int i ) const { return at(i); } + T& operator() ( int i ) { return data_[i]; } + + const T* data() const { return data_; } + T* data() { return data_; } + + void operator+= ( const TinyVector& v ) + { + for ( int i = 0; i < N; ++i ) { + data_[i] += v.data_[i]; + } + } + + void operator-= ( const TinyVector& v ) + { + for ( int i = 0; i < N; ++i ) { + data_[i] -= v.data_[i]; + } + } + + void operator*= ( const TinyVector& v ) + { + for ( int i = 0; i < N; ++i ) { + data_[i] *= v.data_[i]; + } + } + + void operator*= ( const T& x ) + { + for ( int i = 0; i < N; ++i ) { + data_[i] *= x; + } + } + + void operator/= ( const T& x ) + { + for ( int i = 0; i < N; ++i ) { + data_[i] /= x; + } + } + +private: + T data_[N]; +}; + +template< typename T, int N > +TinyVector::TinyVector() +{ +} + +template< typename T, int N > +TinyVector::TinyVector( const T& value ) +{ + for ( int i = 0; i < N; ++i ) { + data_[i] = value; + } +} + +template< typename T, int N > +template< typename T2 > +TinyVector::TinyVector( const TinyVector& v ) +{ + *this = v; +} + +template< typename T, int N > +template< typename T2 > +TinyVector& TinyVector::operator= ( const TinyVector& v ) +{ + for ( int i = 0; i < N; ++i ) { + data_[i] = v(i); + } + return *this; +} + +template< typename T1, typename T2, int N > +TinyVector< typename BinaryNumericTraits::OpResult, N > operator+ ( + const TinyVector& v1, const TinyVector& v2 ) +{ + TinyVector< typename BinaryNumericTraits::OpResult, N > v3(v1); + v3 += v2; + return v3; +} + +template< typename T1, typename T2, int N > +TinyVector< typename BinaryNumericTraits::OpResult, N > operator- ( + const TinyVector& v1, const TinyVector& v2 ) +{ + TinyVector< typename BinaryNumericTraits::OpResult, N > v3(v1); + v3 -= v2; + return v3; +} + +template< typename T1, typename T2, int N > +TinyVector< typename BinaryNumericTraits::OpResult, N > operator* ( + const TinyVector& v1, const TinyVector& v2 ) +{ + TinyVector< typename BinaryNumericTraits::OpResult, N > v3(v1); + v3 *= v2; + return v3; +} + +template< typename T1, typename T2, int N > +TinyVector< typename BinaryNumericTraits::OpResult, N > operator* ( + const TinyVector& v1, const T2& x ) +{ + TinyVector< typename BinaryNumericTraits::OpResult, N > v2(v1); + v2 *= x; + return v2; +} + +template< typename T, int N > +TinyVector operator* ( const T& x, TinyVector v1 ) +{ + for ( int i = 0; i < N; ++i ) { + v1(i) = x * v1(i); + } + return v1; +} + +template< typename T1, typename T2, int N > +TinyVector< typename BinaryNumericTraits::OpResult, N > operator* ( + const T2& x, const TinyVector& v1 ) +{ + return x * + TinyVector< typename BinaryNumericTraits::OpResult, N >(v1); +} + +template< typename T1, typename T2, int N > +TinyVector< typename BinaryNumericTraits::OpResult, N > operator/ ( + const TinyVector& v1, const TinyVector& v2 ) +{ + TinyVector< typename BinaryNumericTraits::OpResult, N > v3(v1); + v3 /= v2; + return v3; +} + +template< typename T1, typename T2, int N > +TinyVector< typename BinaryNumericTraits::OpResult, N > operator/ ( + const TinyVector& v1, const T2& x ) +{ + TinyVector< typename BinaryNumericTraits::OpResult, N > v2(v1); + v2 /= x; + return v2; +} + +template< typename T, int N > +T sum( const TinyVector& v ) +{ + T sum(0); + for ( int i = 0; i < N; ++i ) { + sum += v(i); + } + return sum; +} + +template< typename T, int N > +T prod( const TinyVector& v ) +{ + T prod(1); + for ( int i = 0; i < N; ++i ) { + prod *= v(i); + } + return prod; +} + +template< typename T, int N > +TinyVector cumprod( const TinyVector& v ) +{ + TinyVector p; + T prev(1); + for ( int i = 0; i < N; ++i ) { + p(i) = prev = prev * v(i); + } + return p; +} + +template< typename T, int N > +T norm( const TinyVector& v ) +{ + return sqrt( sum(v*v) ); +} + + +#endif diff --git a/src/apMetalBSDF/apMetalBSDF.cpp b/src/apMetalBSDF/apMetalBSDF.cpp new file mode 100644 index 0000000..9ccdbd9 --- /dev/null +++ b/src/apMetalBSDF/apMetalBSDF.cpp @@ -0,0 +1,95 @@ +#include "ai.h" + +AI_SHADER_NODE_EXPORT_METHODS(apMetalBSDF) + +enum apMetalBSDFParams +{ + p_weight, + p_distribution, + p_n_ior, + p_k_ior, + p_roughness_u, + p_roughness_v, + p_opacity +}; + +static const char* DistributionNames[] +{ + "MICROFACET_BECKMANN", + "MICROFACET_GGX", + NULL +}; + +struct ShaderData +{ + int distribution; + float n_ior; + float k_ior; + float ru; + float rv; +}; + +node_parameters +{ + AiParameterRGB("weight", 0.5, 0.5, 0.5); + AiParameterEnum("distribution", 0, DistributionNames); + AiParameterFlt("n_ior", 0); + AiParameterFlt("k_ior", 0); + AiParameterFlt("roughness_u", 0); + AiParameterFlt("roughness_v", 0); + AiParameterRGB("opacity", 1, 1, 1); +} + +node_initialize +{ + ShaderData *data = (ShaderData *)AiMalloc(sizeof(ShaderData)); + AiNodeSetLocalData(node, data); +} + +node_update +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + data->distribution = AiNodeGetInt(node, "distribution"); + data->n_ior = AiNodeGetFlt(node, "n_ior"); + data->k_ior = AiNodeGetFlt(node, "k_ior"); + data->ru = AiNodeGetFlt(node, "roughness_u"); + data->rv = AiNodeGetFlt(node, "roughness_v"); +} + +node_finish +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AiFree(data); +} + +shader_evaluate +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AtRGB weight = AiShaderEvalParamRGB(p_weight); + AtRGB opacity = AiShaderEvalParamRGB(p_opacity); + int distribution = data->distribution ? AI_MICROFACET_BECKMANN : AI_MICROFACET_GGX; + + AtBSDF *bsdf = AiMicrofacetRefractionBSDF(sg, weight * opacity, + distribution, + sg->Nf, &sg->dPdu, + data->n_ior, data->k_ior, + data->ru, data->rv); + + AtClosureList closures; + closures.add(bsdf); + closures.add(AiClosureTransparent(sg, 1.0 - opacity)); + sg->out.CLOSURE() = closures; +} + +node_loader +{ + if (i > 0) + return false; + + node->methods = apMetalBSDF; + node->output_type = AI_TYPE_CLOSURE; + node->name = "apMetalBSDF"; + node->node_type = AI_NODE_SHADER; + strcpy(node->version, AI_VERSION); + return true; +} \ No newline at end of file diff --git a/src/apMetalBSDF/apMetalBSDF.mtd b/src/apMetalBSDF/apMetalBSDF.mtd new file mode 100644 index 0000000..a98e5ae --- /dev/null +++ b/src/apMetalBSDF/apMetalBSDF.mtd @@ -0,0 +1,39 @@ +[node apMetalBSDF] + maya.name STRING "apMetalBSDF" + maya.id INT 0x0005111 + maya.classification STRING "shader/surface" + + [attr weight] + desc STRING "Weight" + maya.keyable BOOL false + linkable BOOL true + + [attr distribution] + desc STRING "AI_MICROFACET_BECKMANN or AI_MICROFACET_GGX" + maya.keyable BOOL false + linkable BOOL false + + [attr n_ior] + desc STRING "Real part of the complex refractive index for Fresnel" + maya.keyable BOOL false + linkable BOOL false + + [attr k_ior] + desc STRING "Imaginary part of the complex refractive index for Fresnel" + maya.keyable BOOL false + linkable BOOL false + + [attr roughness_u] + desc STRING "Specular roughness along the U direction" + maya.keyable BOOL false + linkable BOOL false + + [attr roughness_v] + desc STRING "Specular roughness along the V direction" + maya.keyable BOOL false + linkable BOOL false + + [attr opacity] + desc STRING "Opacity" + maya.keyable BOOL false + linkable BOOL true diff --git a/src/apMetalBSDF/apMetalBSDFTemplate.py b/src/apMetalBSDF/apMetalBSDFTemplate.py new file mode 100644 index 0000000..04aee3f --- /dev/null +++ b/src/apMetalBSDF/apMetalBSDFTemplate.py @@ -0,0 +1,20 @@ +import maya.mel +from mtoa.ui.ae.shaderTemplate import ShaderAETemplate + +class AEapMetalBSDFTemplate(ShaderAETemplate): + def setup(self): + self.addSwatch() + self.beginScrollLayout() + self.beginLayout("BSDF Attribues", collapse=False) + self.addControl('weight', label='Weight') + self.addControl('distribute', label='Distribute', annotation='MICROFACET_BECKMANN or MICROFACET_GGX') + self.addControl('n_ior', label='N IOR', annotation='Real part of the complex refractive index for Fresnel') + self.addControl('k_ior', label='K IOR', annotation='Imaginary part of the complex refractive index for Fresnel') + self.addControl('roughness_u', label='Roughness U', annotation='Specular roughness along the U direction') + self.addControl('roughness_v', label='Roughness V', annotation='Specular roughness along the V direction') + self.addControl('opacity', label='Opacity') + self.endLayout() + maya.mel.eval('AEdependNodeTemplate '+self.nodeName) + self.addExtraControls() + self.endScrollLayout() + \ No newline at end of file diff --git a/src/apMicrofacetBSDF/apMicrofacetBSDF.cpp b/src/apMicrofacetBSDF/apMicrofacetBSDF.cpp new file mode 100644 index 0000000..66af028 --- /dev/null +++ b/src/apMicrofacetBSDF/apMicrofacetBSDF.cpp @@ -0,0 +1,105 @@ +#include "ai.h" + +AI_SHADER_NODE_EXPORT_METHODS(apMicrofacetBSDF) + +enum apMicrofacetBSDFParams +{ + p_weight, + p_distribution, + p_eta, + p_roughness_u, + p_roughness_v, + p_exit_type, + p_opacity +}; + +static const char* DistributionNames[] +{ + "MICROFACET_BECKMANN", + "MICROFACET_GGX", + NULL +}; + +static const char* ExitTypeNames[] +{ + "Zero", + "Background", + "White", + NULL +}; + +struct ShaderData +{ + int distribution; + float eta; + float ru; + float rv; + int exit_type; +}; + +node_parameters +{ + AiParameterRGB("weight", 0.5, 0.5, 0.5); + AiParameterEnum("distribution", 0, DistributionNames); + AiParameterFlt("eta", 0); + AiParameterFlt("roughness_u", 0); + AiParameterFlt("roughness_v", 0); + AiParameterEnum("exit_type", 0, ExitTypeNames); + AiParameterRGB("opacity", 1, 1, 1); +} + +node_initialize +{ + ShaderData *data = (ShaderData *)AiMalloc(sizeof(ShaderData)); + AiNodeSetLocalData(node, data); +} + +node_update +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + data->distribution = AiNodeGetInt(node, "distribution"); + data->eta = AiNodeGetFlt(node, "eta"); + data->ru = AiNodeGetFlt(node, "roughness_u"); + data->rv = AiNodeGetFlt(node, "roughness_v"); + data->exit_type = AiNodeGetInt(node, "exit_type"); +} + +node_finish +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AiFree(data); +} + +shader_evaluate +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AtRGB weight = AiShaderEvalParamRGB(p_weight); + AtRGB opacity = AiShaderEvalParamRGB(p_opacity); + int distribution = data->distribution ? AI_MICROFACET_BECKMANN : AI_MICROFACET_GGX; + int exit_type = 0; + if (data->exit_type == 1) exit_type = AI_BSDF_LOBE_EXIT_BACKGROUND; + if (data->exit_type == 2) exit_type = AI_BSDF_LOBE_EXIT_WHITE; + + AtBSDF *bsdf = AiMicrofacetBSDF(sg, weight * opacity, + distribution, + sg->Nf, &sg->dPdu, data->eta, + data->ru, data->rv, + exit_type); + AtClosureList closures; + closures.add(bsdf); + closures.add(AiClosureTransparent(sg, 1.0 - opacity)); + sg->out.CLOSURE() = closures; +} + +node_loader +{ + if (i > 0) + return false; + + node->methods = apMicrofacetBSDF; + node->output_type = AI_TYPE_CLOSURE; + node->name = "apMicrofacetBSDF"; + node->node_type = AI_NODE_SHADER; + strcpy(node->version, AI_VERSION); + return true; +} \ No newline at end of file diff --git a/src/apMicrofacetBSDF/apMicrofacetBSDF.mtd b/src/apMicrofacetBSDF/apMicrofacetBSDF.mtd new file mode 100644 index 0000000..751a64f --- /dev/null +++ b/src/apMicrofacetBSDF/apMicrofacetBSDF.mtd @@ -0,0 +1,39 @@ +[node apMicrofacetBSDF] + maya.name STRING "apMicrofacetBSDF" + maya.id INT 0x0005109 + maya.classification STRING "shader/surface" + + [attr weight] + desc STRING "Weight" + maya.keyable BOOL false + linkable BOOL true + + [attr distribution] + desc STRING "AI_MICROFACET_BECKMANN or AI_MICROFACET_GGX" + maya.keyable BOOL false + linkable BOOL false + + [attr eta] + desc STRING "Refractive index for Fresnel, use 0 to disable Fresnel" + maya.keyable BOOL false + linkable BOOL false + + [attr roughness_u] + desc STRING "Specular roughness along the U direction" + maya.keyable BOOL false + linkable BOOL false + + [attr roughness_v] + desc STRING "Specular roughness along the V direction" + maya.keyable BOOL false + linkable BOOL false + + [attr exit_type] + desc STRING "zero, AI_BSDF_LOBE_EXIT_BACKGROUND or AI_BSDF_LOBE_EXIT_WHITE" + maya.keyable BOOL false + linkable BOOL false + + [attr opacity] + desc STRING "Opacity" + maya.keyable BOOL false + linkable BOOL true diff --git a/src/apMicrofacetBSDF/apMicrofacetBSDFTemplate.py b/src/apMicrofacetBSDF/apMicrofacetBSDFTemplate.py new file mode 100644 index 0000000..ff0a003 --- /dev/null +++ b/src/apMicrofacetBSDF/apMicrofacetBSDFTemplate.py @@ -0,0 +1,20 @@ +import maya.mel +from mtoa.ui.ae.shaderTemplate import ShaderAETemplate + +class AEapMicrofacetBSDFTemplate(ShaderAETemplate): + def setup(self): + self.addSwatch() + self.beginScrollLayout() + self.beginLayout("BSDF Attribues", collapse=False) + self.addControl('weight', label='Weight') + self.addControl('distribute', label='Distribute', annotation='MICROFACET_BECKMANN or MICROFACET_GGX') + self.addControl('eta', label='IOR', annotation='Refractive index for Fresnel, use 0 to disable Fresnel') + self.addControl('roughness_u', label='Roughness U', annotation='Specular roughness along the U direction') + self.addControl('roughness_v', label='Roughness V', annotation='Specular roughness along the V direction') + self.addControl('exit_type', label='Exit Type', annotation='zero, background or white') + self.addControl('opacity', label='Opacity') + self.endLayout() + maya.mel.eval('AEdependNodeTemplate '+self.nodeName) + self.addExtraControls() + self.endScrollLayout() + \ No newline at end of file diff --git a/src/apMicrofacetRefractionBSDF/apMicrofacetRefractionBSDF.cpp b/src/apMicrofacetRefractionBSDF/apMicrofacetRefractionBSDF.cpp new file mode 100644 index 0000000..41c278e --- /dev/null +++ b/src/apMicrofacetRefractionBSDF/apMicrofacetRefractionBSDF.cpp @@ -0,0 +1,118 @@ +#include "ai.h" + +AI_SHADER_NODE_EXPORT_METHODS(apMicrofacetRefractionBSDF) + +enum apMicrofacetRefractionBSDFParams +{ + p_weight, + p_distribution, + p_eta, + p_roughness_u, + p_roughness_v, + p_dispersion, + p_use_fresnel, + p_interior, + p_exit_type, + p_opacity +}; + +static const char* DistributionNames[] +{ + "MICROFACET_BECKMANN", + "MICROFACET_GGX", + NULL +}; + +static const char* ExitTypeNames[] +{ + "Zero", + "Background", + "White", + NULL +}; + +struct ShaderData +{ + int distribution; + float eta; + float ru; + float rv; + float dispersion; + bool use_fresnel; + int exit_type; +}; + +node_parameters +{ + AiParameterRGB("weight", 0.5, 0.5, 0.5); + AiParameterEnum("distribution", 0, DistributionNames); + AiParameterFlt("eta", 0); + AiParameterFlt("roughness_u", 0); + AiParameterFlt("roughness_v", 0); + AiParameterFlt("dispersion", 0); + AiParameterBool("use_fresnel", 0); + AiParameterClosure("interior"); + AiParameterEnum("exit_type", 0, ExitTypeNames); + AiParameterRGB("opacity", 1, 1, 1); +} + +node_initialize +{ + ShaderData *data = (ShaderData *)AiMalloc(sizeof(ShaderData)); + AiNodeSetLocalData(node, data); +} + +node_update +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + data->distribution = AiNodeGetInt(node, "distribution"); + data->eta = AiNodeGetFlt(node, "eta"); + data->ru = AiNodeGetFlt(node, "roughness_u"); + data->rv = AiNodeGetFlt(node, "roughness_v"); + data->dispersion = AiNodeGetFlt(node, "dispersion"); + data->use_fresnel = AiNodeGetBool(node, "use_fresnel"); + data->exit_type = AiNodeGetInt(node, "exit_type"); +} + +node_finish +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AiFree(data); +} + +shader_evaluate +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AtRGB weight = AiShaderEvalParamRGB(p_weight); + AtRGB opacity = AiShaderEvalParamRGB(p_opacity); + int distribution = data->distribution ? AI_MICROFACET_BECKMANN : AI_MICROFACET_GGX; + int exit_type = 0; + if (data->exit_type == 1) exit_type = AI_BSDF_LOBE_EXIT_BACKGROUND; + if (data->exit_type == 2) exit_type = AI_BSDF_LOBE_EXIT_WHITE; + AtClosureList interior; + interior.add(AiShaderEvalParamClosure(p_interior)); + AtBSDF *bsdf = AiMicrofacetRefractionBSDF(sg, weight * opacity, + distribution, + sg->Nf, &sg->dPdu, data->eta, + data->ru, data->rv, data->dispersion, + data->use_fresnel, + interior, + exit_type); + AtClosureList closures; + closures.add(bsdf); + closures.add(AiClosureTransparent(sg, 1.0 - opacity)); + sg->out.CLOSURE() = closures; +} + +node_loader +{ + if (i > 0) + return false; + + node->methods = apMicrofacetRefractionBSDF; + node->output_type = AI_TYPE_CLOSURE; + node->name = "apMicrofacetRefractionBSDF"; + node->node_type = AI_NODE_SHADER; + strcpy(node->version, AI_VERSION); + return true; +} \ No newline at end of file diff --git a/src/apMicrofacetRefractionBSDF/apMicrofacetRefractionBSDF.mtd b/src/apMicrofacetRefractionBSDF/apMicrofacetRefractionBSDF.mtd new file mode 100644 index 0000000..b1fdfcc --- /dev/null +++ b/src/apMicrofacetRefractionBSDF/apMicrofacetRefractionBSDF.mtd @@ -0,0 +1,54 @@ +[node apMicrofacetRefractionBSDF] + maya.name STRING "apMicrofacetRefractionBSDF" + maya.id INT 0x0005110 + maya.classification STRING "shader/surface" + + [attr weight] + desc STRING "Weight" + maya.keyable BOOL false + linkable BOOL true + + [attr distribution] + desc STRING "AI_MICROFACET_BECKMANN or AI_MICROFACET_GGX" + maya.keyable BOOL false + linkable BOOL false + + [attr eta] + desc STRING "Refractive index for Fresnel, use 0 to disable Fresnel" + maya.keyable BOOL false + linkable BOOL false + + [attr roughness_u] + desc STRING "Specular roughness along the U direction" + maya.keyable BOOL false + linkable BOOL false + + [attr roughness_v] + desc STRING "Specular roughness along the V direction" + maya.keyable BOOL false + linkable BOOL false + + [attr dispersion] + desc STRING "Cauchy coefficient for dispersion. zero for no dispersion, higher values give more dispersion" + maya.keyable BOOL false + linkable BOOL false + + [attr use_fresnel] + desc STRING "Set to true to include Fresnel term" + maya.keyable BOOL false + linkable BOOL false + + [attr interior] + desc STRING "Volume closures that define the interior of the object, like volume absorption" + maya.keyable BOOL false + linkable BOOL false + + [attr exit_type] + desc STRING "zero, AI_BSDF_LOBE_EXIT_BACKGROUND or AI_BSDF_LOBE_EXIT_WHITE" + maya.keyable BOOL false + linkable BOOL false + + [attr opacity] + desc STRING "Opacity" + maya.keyable BOOL false + linkable BOOL true diff --git a/src/apMicrofacetRefractionBSDF/apMicrofacetRefractionBSDFemplate.py b/src/apMicrofacetRefractionBSDF/apMicrofacetRefractionBSDFemplate.py new file mode 100644 index 0000000..b9d8cef --- /dev/null +++ b/src/apMicrofacetRefractionBSDF/apMicrofacetRefractionBSDFemplate.py @@ -0,0 +1,23 @@ +import maya.mel +from mtoa.ui.ae.shaderTemplate import ShaderAETemplate + +class AEapMicrofacetRefractionBSDFTemplate(ShaderAETemplate): + def setup(self): + self.addSwatch() + self.beginScrollLayout() + self.beginLayout("BSDF Attribues", collapse=False) + self.addControl('weight', label='Weight') + self.addControl('distribute', label='Distribute', annotation='MICROFACET_BECKMANN or MICROFACET_GGX') + self.addControl('eta', label='IOR', annotation='Refractive index for Fresnel, use 0 to disable Fresnel') + self.addControl('roughness_u', label='Roughness U', annotation='Specular roughness along the U direction') + self.addControl('roughness_v', label='Roughness V', annotation='Specular roughness along the V direction') + self.addControl('dispersion', label='Dispersion', annotation='Cauchy coefficient for dispersion. zero for no dispersion, higher values give more dispersion') + self.addControl('use_fresnel', label='Use Fresnel', annotation='Set to true to include Fresnel term') + self.addControl('interior', label='Interior', annotation='Volume closures that define the interior of the object, like volume absorption') + self.addControl('exit_type', label='Exit Type', annotation='zero, background or white') + self.addControl('opacity', label='Opacity') + self.endLayout() + maya.mel.eval('AEdependNodeTemplate '+self.nodeName) + self.addExtraControls() + self.endScrollLayout() + \ No newline at end of file diff --git a/src/apMotionVector/apMotionVector.cpp b/src/apMotionVector/apMotionVector.cpp new file mode 100644 index 0000000..6388b17 --- /dev/null +++ b/src/apMotionVector/apMotionVector.cpp @@ -0,0 +1,75 @@ +#include "ai.h" + +AI_SHADER_NODE_EXPORT_METHODS(apMotionVector); + +enum apMotionVectorParams +{ + p_mode, + p_input, + p_opacity, + p_normalize, +}; +const char *ModeNames[] = + { + "RevisionFX ReelSmart Motion Blur (RSMB)", + "RevisionFX SmoothKit", + NULL}; +const char *NormalizeSizeNames[] = + { + "16", + "32", + "64", + "128", + "256", + "512", + "1024", + "2048", + "4096", + NULL}; + +struct ShaderData +{ + int mode; + int normalize; + float frame; + float shutter_start; + float shutter_end; +}; + +node_parameters +{ + AiParameterEnum("mode", 0, ModeNames); + AiParameterEnum("normalize", 0, NormalizeSizeNames); +} + +node_initialize +{ + ShaderData *data = (ShaderData *)AiMalloc(sizeof(ShaderData)); + AiNodeSetLocalData(node, data); +} + +node_update +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + data->mode = AiNodeGetInt(node, "mode"); + data->normalize = AiNodeGetInt(node, "normalize"); + AtNode *option = AiUniverseGetOptions(); + data->frame = AiNodeGetFlt(node, "frame"); + AtNode *camera = AiUniverseGetCamera(); + data->shutter_start = AiNodeGetFlt(camera, "shutter_start"); + data->shutter_end = AiNodeGetFlt(camera, "shutter_end"); +} + +node_finish +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AiFree(data); +} + +shader_evaluate +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + float frame_start = sg->time + data->shutter_start; + AtVector2 mv = AiShaderGlobalsGetPixelMotionVector(sg, frame_start, sg->time); + // TODO +} \ No newline at end of file diff --git a/src/apMotionVector/apMotionVector.mtd b/src/apMotionVector/apMotionVector.mtd new file mode 100644 index 0000000..e69de29 diff --git a/src/apMotionVector/apMotionVectorTemplate.py b/src/apMotionVector/apMotionVectorTemplate.py new file mode 100644 index 0000000..e69de29 diff --git a/src/apOrenNayerBSDF/apOrenNayerBSDF.cpp b/src/apOrenNayerBSDF/apOrenNayerBSDF.cpp new file mode 100644 index 0000000..05fd622 --- /dev/null +++ b/src/apOrenNayerBSDF/apOrenNayerBSDF.cpp @@ -0,0 +1,70 @@ +#include "ai.h" + +AI_SHADER_NODE_EXPORT_METHODS(apOrenNayerBSDF) + +enum apClosureParams +{ + p_weight, + p_roughness, + p_transmission, + p_opacity +}; + + +struct ShaderData +{ + float roughness; + bool transmission; +}; + +node_parameters +{ + AiParameterRGB("weight", 0.5, 0.5, 0.5); + AiParameterFlt("roughness", 0); + AiParameterBool("transmission", 0); + AiParameterRGB("opacity", 1, 1, 1); +} + +node_initialize +{ + ShaderData *data = (ShaderData *)AiMalloc(sizeof(ShaderData)); + AiNodeSetLocalData(node, data); +} + +node_update +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + data->roughness = AiNodeGetFlt(node, "roughness"); + data->transmission = AiNodeGetBool(node, "transmission"); +} + +node_finish +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AiFree(data); +} + +shader_evaluate +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AtRGB weight = AiShaderEvalParamRGB(p_weight); + AtRGB opacity = AiShaderEvalParamRGB(p_opacity); + AtBSDF *bsdf = AiOrenNayarBSDF(sg, weight * opacity, sg->N, data->roughness, data->transmission); + AtClosureList closures; + closures.add(bsdf); + closures.add(AiClosureTransparent(sg, 1.0 - opacity)); + sg->out.CLOSURE() = closures; +} + +node_loader +{ + if (i > 0) + return false; + + node->methods = apOrenNayerBSDF; + node->output_type = AI_TYPE_CLOSURE; + node->name = "apOrenNayerBSDF"; + node->node_type = AI_NODE_SHADER; + strcpy(node->version, AI_VERSION); + return true; +} \ No newline at end of file diff --git a/src/apOrenNayerBSDF/apOrenNayerBSDF.mtd b/src/apOrenNayerBSDF/apOrenNayerBSDF.mtd new file mode 100644 index 0000000..7ebf2f1 --- /dev/null +++ b/src/apOrenNayerBSDF/apOrenNayerBSDF.mtd @@ -0,0 +1,24 @@ +[node apOrenNayerBSDF] + maya.name STRING "apOrenNayerBSDF" + maya.id INT 0x0005108 + maya.classification STRING "shader/surface" + + [attr diffuse] + desc STRING "Diffuse" + maya.keyable BOOL false + linkable BOOL true + + [attr roughness] + desc STRING "Surface roughness, normalized in the [0, 1] range" + maya.keyable BOOL false + linkable BOOL true + + [attr transmission] + desc STRING "Use diffuse transmission instead of reflection" + maya.keyable BOOL false + linkable BOOL false + + [attr opacity] + desc STRING "Opacity" + maya.keyable BOOL false + linkable BOOL true diff --git a/src/apOrenNayerBSDF/apOrenNayerBSDFTemplate.py b/src/apOrenNayerBSDF/apOrenNayerBSDFTemplate.py new file mode 100644 index 0000000..b619c28 --- /dev/null +++ b/src/apOrenNayerBSDF/apOrenNayerBSDFTemplate.py @@ -0,0 +1,17 @@ +import maya.mel +from mtoa.ui.ae.shaderTemplate import ShaderAETemplate + +class AEapOrenNayerBSDFTemplate(ShaderAETemplate): + def setup(self): + self.addSwatch() + self.beginScrollLayout() + self.beginLayout("BSDF Attribues", collapse=False) + self.addControl('weight', label='Weight') + self.addControl('roughness', label='Roughness', annotation='Surface roughness, normalized in the [0, 1] range') + self.addControl('transmission', label='Transmission', annotation='Use diffuse transmission instead of reflection') + self.addControl('opacity', label='Opacity') + self.endLayout() + maya.mel.eval('AEdependNodeTemplate '+self.nodeName) + self.addExtraControls() + self.endScrollLayout() + \ No newline at end of file diff --git a/src/apParallaxMap/CMakeLists.txt b/src/apParallaxMap/CMakeLists.txt new file mode 100644 index 0000000..053d915 --- /dev/null +++ b/src/apParallaxMap/CMakeLists.txt @@ -0,0 +1,23 @@ +set(SHADER apParallaxMap) + +set(SRC_FILES + "apParallaxMap.cpp") + +set(META_FILES + "apParallaxMap.mtd") + +set(TEMPLATE_FILES + "apParallaxMapTemplate.py") + +include_directories(${ARNOLD_INCLUDE_PATH}) +add_library(${SHADER} SHARED ${SRC_FILES}) +set_target_properties(${SHADER} PROPERTIES PREFIX "") + +target_link_libraries(${SHADER} ${ARNOLD_AI_LIBRARY}) + +set(INSTALL_SHADER_TARGET "${CMAKE_INSTALL_PREFIX}/${ARNOLD_VERSION}/${CMAKE_PROJECT_NAME}/shaders") +set(INSTALL_TEMPLATE_TARGET "${CMAKE_INSTALL_PREFIX}/${ARNOLD_VERSION}/${CMAKE_PROJECT_NAME}/templates") + +install(TARGETS ${SHADER} RUNTIME DESTINATION ${INSTALL_SHADER_TARGET}) +install(FILES ${META_FILES} DESTINATION ${INSTALL_SHADER_TARGET}) +install(FILES ${TEMPLATE_FILES} DESTINATION ${INSTALL_TEMPLATE_TARGET}) \ No newline at end of file diff --git a/src/apParallaxMap/apParallaxMap.cpp b/src/apParallaxMap/apParallaxMap.cpp new file mode 100644 index 0000000..220d9c6 --- /dev/null +++ b/src/apParallaxMap/apParallaxMap.cpp @@ -0,0 +1,268 @@ +#include "ai.h" +#include + +AI_SHADER_NODE_EXPORT_METHODS(apParallaxMap) +enum apParallaxMapParams +{ + p_standard_surface, + p_parallax_map, + p_parallax_value, + p_self_shadow, + p_shadow_opacity +}; + + + +struct ShaderData +{ + float parallax_value; + int min_layers; + int max_layers; + int search_number; + bool self_shadow; +}; + +struct SgCache +{ + void init(AtShaderGlobals *sg) + { + u = sg->u; + v = sg->v; + } + void restore(AtShaderGlobals *sg) + { + sg->u = u; + sg->v = v; + } + float u; + float v; +}; + +float compute_shadow_multiplier(AtShaderGlobals *sg, AtNode *node, ShaderData *data) +{ + // AiMsgInfo("P : %f, %f, %f", sg->P.x, sg->P.y, sg->P.z); + // AiMsgInfo("Rd : %f, %f, %f", sg->Rd.x, sg->Rd.y, sg->Rd.z); + + AtVector world_position = sg->P; + AtVector world_tangent = sg->dPdu; + AtVector world_bitangent = sg->dPdv; + AtVector world_normal = sg->N; + + float shadow_multiplier = 1; + const float min_layers = 15; + const float max_layers = 30; + + AtVector light_dir_in_tangent_space = AtVector(AiV3Dot(sg->Rd, world_tangent), + AiV3Dot(sg->Rd, world_bitangent), + AiV3Dot(sg->Rd, world_normal)); + + AtVector L(AiV3Normalize(light_dir_in_tangent_space)); + // calculate lighting only for surface oriented to the light source + if (AiV3Dot(AtVector(0, 0, 1), L) > 0) + { + // Get coord and height from same shading state + AtVector2 init_texture_coord; + float init_height = 0; + AiStateGetMsgVec2(AtString("init_texcoord"), &init_texture_coord); + AiStateGetMsgFlt(AtString("init_height"), &init_height); + + shadow_multiplier = 0; + float num_samples_under_surface = 0; + // calculate initial parameters + float num_layers = AiLerp(abs(AiV3Dot(AtVector(0, 0, 1), L)), min_layers, max_layers); + float layer_height = init_height / num_layers; + AtVector2 dtex = data->parallax_value * AtVector2(L.x, L.y) / L.z / num_layers; + // current parameters + float current_layer_height = init_height - layer_height; + + AtVector2 current_texture_coord = init_texture_coord + dtex; + + sg->u = current_texture_coord.x; + sg->v = current_texture_coord.y; + + float height_from_texture = AiShaderEvalParamRGB(p_parallax_map).r; + int step_index = 0; + while (current_layer_height > 0) + { + if (height_from_texture < current_layer_height) + { + num_samples_under_surface += 1; + float new_shadow_multiplier = (current_layer_height - height_from_texture) * (1.0 - step_index / num_layers); + shadow_multiplier = AiMax(shadow_multiplier, new_shadow_multiplier); + } + // offset to the next layer + step_index += 1; + current_layer_height -= layer_height; + current_texture_coord += dtex; + sg->u = current_texture_coord.x; + sg->v = current_texture_coord.y; + height_from_texture = AiShaderEvalParamRGB(p_parallax_map).r; + } + // Shadowing factor should be 1 if there were no points under the surface + if (num_samples_under_surface < 1) + { + shadow_multiplier = 1; + } + else + { + shadow_multiplier = 1.0 - shadow_multiplier; + AiMsgInfo("shadow : %f", shadow_multiplier); + } + } + return shadow_multiplier; +} + + +node_parameters +{ + AiParameterClosure("standard_surface"); + AiParameterRGB("parallax_map", 0, 0, 0); + AiParameterFlt("parallax_value", 0); + AiParameterInt("min_layers", 64); + AiParameterInt("max_layers", 128); + AiParameterInt("search_number", 5); + AiParameterBool("self_shadow", true); + AiParameterRGB("shadow_opacity", 1.0, 1.0, 1.0); +} + +node_initialize +{ + ShaderData *data = (ShaderData *)AiMalloc(sizeof(ShaderData)); + AiNodeSetLocalData(node, data); +} + +node_update +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + data->parallax_value = AiNodeGetFlt(node, "parallax_value"); + data->min_layers = AiNodeGetInt(node, "min_layers"); + data->max_layers = AiNodeGetInt(node, "max_layers"); + data->search_number = AiNodeGetInt(node, "search_number"); + data->self_shadow = AiNodeGetBool(node, "self_shadow"); +} + +node_finish +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AiFree(data); +} + +shader_evaluate +{ + AtVector world_position = sg->P; + AtVector world_tangent =sg->dPdu; + AtVector world_bitangent = sg->dPdv; + AtVector world_normal = sg->N; + + + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + + // shadow shader calculate + if (sg->Rt & AI_RAY_SHADOW) { + return; + // float shadow_multiplier = compute_shadow_multiplier(sg, node, &data); + // AtRGB shadow_opacity = AiShaderEvalParamRGB(p_shadow_opacity); + // sg->out.CLOSURE() = AiClosureTransparent(sg, AtRGB(1.0-shadow_multiplier)); + // return; + } + + AtVector2 T(sg->u, sg->v); + // transform direction to the camera to tangent space + AtVector view_dir_in_tangent_space = AtVector(AiV3Dot(sg->Rd, world_tangent), + AiV3Dot(sg->Rd, world_bitangent), + AiV3Dot(sg->Rd, world_normal)); + + AtVector V(AiV3Normalize(view_dir_in_tangent_space)); + + + float num_layers = AiLerp(abs(AiV3Dot(AtVector(0, 0, 1), V)), data->max_layers, data->min_layers); + + // height of each layer + float layer_height = 1.0 / num_layers; + // depth of current layer + float current_layer_height = 0; + // shift of texture coordinates for each iteration + AtVector2 dtex = data->parallax_value * AtVector2(V.x, V.y) / V.z / num_layers; + + // current texture coordinate + AtVector2 current_texture_coord = T; + + // depth of heightmap + float height_from_texture = AiShaderEvalParamRGB(p_parallax_map).r; + + // cache sg->u and sg->v + // SgCache sg_cache; + // sg_cache.init(sg); + + while (height_from_texture > current_layer_height) + { + // go to next layer + current_layer_height += layer_height; + // shift texture coordinate along V + current_texture_coord -= dtex; + sg->u = current_texture_coord.x; + sg->v = current_texture_coord.y; + // new depth from heightmap + height_from_texture = AiShaderEvalParamRGB(p_parallax_map).r; + } + + /////////////////////////////////////////////////////////// + // Start of Relief Parallax Mapping + + // decrease shift and height of layer by half + AtVector2 delta_tex_coord = dtex / 2; + float delta_height = layer_height / 2; + + // return to the mid point of previous layer + current_texture_coord += delta_tex_coord; + current_layer_height -= delta_height; + + // binary search to increase percsion of Steep Parallax Mapping + int num_searches = data->search_number; + + for (int i = 0; i < num_searches; i++) { + // decrease shift and height of layer by half + delta_tex_coord /= 2; + delta_height /= 2; + + sg->u = current_texture_coord.x; + sg->v = current_texture_coord.y; + + // new depth from heightmap + height_from_texture = AiShaderEvalParamRGB(p_parallax_map).r; + + // shift along or agains vector V + if (height_from_texture > current_layer_height) // below the surface + { + current_texture_coord -= delta_tex_coord; + current_layer_height += delta_height; + } + else // above the surface + { + current_texture_coord += delta_tex_coord; + current_layer_height -= delta_height; + } + } + + sg->u = current_texture_coord.x; + sg->v = current_texture_coord.y; + + AiStateSetMsgVec2(AtString("init_texcoord"), current_texture_coord); + AiStateSetMsgFlt(AtString("init_height"), height_from_texture); + + sg->out.CLOSURE() = AiShaderEvalParamClosure(p_standard_surface); + return; +} + +node_loader +{ + if (i > 0) + return false; + + node->methods = apParallaxMap; + node->output_type = AI_TYPE_CLOSURE; + node->name = "apParallaxMap"; + node->node_type = AI_NODE_SHADER; + strcpy(node->version, AI_VERSION); + return true; +} diff --git a/src/apParallaxMap/apParallaxMap.mtd b/src/apParallaxMap/apParallaxMap.mtd new file mode 100644 index 0000000..07dfb45 --- /dev/null +++ b/src/apParallaxMap/apParallaxMap.mtd @@ -0,0 +1,43 @@ +[node apParallaxMap] + maya.name STRING "apParallaxMap" + maya.id INT 0x0005106 + maya.classification STRING "shader/surface" + [attr standard_surface] + desc STRING "Standard Surface" + maya.keyable BOOL false + linkable BOOL true + + [attr parallax_map] + desc STRING "Parallax Map" + maya.keyable BOOL false + linkable BOOL true + + [attr parallax_value] + desc STRING "Parallax Value" + maya.keyable BOOL false + linkable BOOL true + + [attr min_layers] + desc STRING "Min Layers" + maya.keyable BOOL false + linkable BOOL false + + [attr max_layers] + desc STRING "Max Layers" + maya.keyable BOOL false + linkable BOOL false + + [attr search_number] + desc STRING "Search Number" + maya.keyable BOOL false + linkable BOOL false + + [attr self_shadow] + desc STRING "Self Shadow" + maya.keyable BOOL false + linkable BOOL false + + [attr shadow_opacity] + desc STRING "Shadow Opacity" + maya.keyable BOOL false + linkable BOOL false \ No newline at end of file diff --git a/src/apParallaxMap/apParallaxMapTemplate.py b/src/apParallaxMap/apParallaxMapTemplate.py new file mode 100644 index 0000000..4e219ba --- /dev/null +++ b/src/apParallaxMap/apParallaxMapTemplate.py @@ -0,0 +1,21 @@ +import maya.mel +from mtoa.ui.ae.shaderTemplate import ShaderAETemplate + +class AEapParallaxMapTemplate(ShaderAETemplate): + def setup(self): + self.addSwatch() + self.beginScrollLayout() + self.beginLayout("Settings", collapse=False) + self.addControl('standard_surface', label='Standard Surface', annotation='Standard Surface Shader') + self.addControl('parallax_map', label='Parallax Map', annotation='Parallax Map') + self.addControl('parallax_value', label='Parallax Value', annotation='Parallax Scale Value') + self.addControl('min_layers', label='Min Layers', annotation='Min Sample Layers') + self.addControl('max_layers', label='Max Layers', annotation='Max Sample Layers') + self.addControl('search_number', label='Search Number', annotation='Max Binary Search Number') + self.addControl('self_shadow', label='Self Shadow', annotation='Self Shadow') + self.addControl('shadow_opacity', label='Shadow Opacity', annotation='Shadow Opacity') + self.endLayout() + maya.mel.eval('AEdependNodeTemplate '+self.nodeName) + self.addExtraControls() + self.endScrollLayout() + diff --git a/src/apSimpleVolume/apSimpleVolume.cpp b/src/apSimpleVolume/apSimpleVolume.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/apSurfaceSample/CMakeLists.txt b/src/apSurfaceSample/CMakeLists.txt new file mode 100644 index 0000000..c91e7bf --- /dev/null +++ b/src/apSurfaceSample/CMakeLists.txt @@ -0,0 +1,23 @@ +set(SHADER apSurfaceSample) + +set(SRC_FILES + "apSurfaceSample.cpp") + +set(META_FILES + "apSurfaceSample.mtd") + +set(TEMPLATE_FILES + "apSurfaceSampleTemplate.py") + +include_directories(${ARNOLD_INCLUDE_PATH}) +add_library(${SHADER} SHARED ${SRC_FILES}) +set_target_properties(${SHADER} PROPERTIES PREFIX "") + +target_link_libraries(${SHADER} ${ARNOLD_AI_LIBRARY}) + +set(INSTALL_SHADER_TARGET "${CMAKE_INSTALL_PREFIX}/${ARNOLD_VERSION}/${CMAKE_PROJECT_NAME}/shaders") +set(INSTALL_TEMPLATE_TARGET "${CMAKE_INSTALL_PREFIX}/${ARNOLD_VERSION}/${CMAKE_PROJECT_NAME}/templates") + +install(TARGETS ${SHADER} RUNTIME DESTINATION ${INSTALL_SHADER_TARGET}) +install(FILES ${META_FILES} DESTINATION ${INSTALL_SHADER_TARGET}) +install(FILES ${TEMPLATE_FILES} DESTINATION ${INSTALL_TEMPLATE_TARGET}) \ No newline at end of file diff --git a/src/apSurfaceSample/apSurfaceSample.cpp b/src/apSurfaceSample/apSurfaceSample.cpp new file mode 100644 index 0000000..b3d9e6a --- /dev/null +++ b/src/apSurfaceSample/apSurfaceSample.cpp @@ -0,0 +1,273 @@ +#include "ai.h" + +AI_SHADER_NODE_EXPORT_METHODS(apSurfaceSample) + +enum apSurfaceSampleParams +{ + p_default_color, + p_sample_direction, + p_custom_direction, + p_sample_data_type, + p_space, + p_normalize, + p_invert, + p_trace_sets, + p_inclusive +}; + +static const char* SampleDirectionNames[] = { + "Surface Normal", + "Camera Direction", + "Custom Direction", + NULL +}; + +static const char* SampleTypeNames[] = { + "Shading Normal (N)", + "Shading Normal without Bump (Ns)", + "Geometry Normal (Ng)", + "Shading Normal face-forward (Nf)", + "Geometry Normal face-forward (Ngf)", + "Shading Point (P)", + "UV Coordinate (uv)", + "Tanget U (dPdu)", + "Tanget V (dPdv)", + "Binormal (dPdu ^ dPdv)", + "Distance (Rl)", + "Shading Color", + "Occlusion", + NULL +}; + +static const char* SampleSpaceNames[] = { + "World Space", + "Object Space", + "Camera Space", + "Tanget Space", + NULL +}; + +struct ShaderData +{ + int sample_direction; + AtVector custom_direction; + int sample_data_type; + int space; + bool normalize; + bool invert; + AtString trace_sets; + bool inclusive; +}; + +node_parameters +{ + AiParameterRGB("default_color", 0, 0, 0); + AiParameterEnum("sample_direction", 0, SampleDirectionNames); + AiParameterVec("custom_direction", 0, 1, 0); + AiParameterEnum("sample_data_type", 0, SampleTypeNames); + AiParameterEnum("space", 0, SampleSpaceNames); + AiParameterBool("normalize", false); + AiParameterBool("invert", false); + AiParameterStr("trace_sets", ""); + AiParameterBool("inclusive", true); +} + +node_initialize +{ + ShaderData *data = (ShaderData *)AiMalloc(sizeof(ShaderData)); + AiNodeSetLocalData(node, data); +} + +node_update +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + data->sample_direction = AiNodeGetInt(node, "sample_direction"); + data->custom_direction = AiNodeGetVec(node, "custom_direction"); + data->sample_data_type = AiNodeGetInt(node, "sample_data_type"); + data->space = AiNodeGetInt(node, "space"); + data->normalize = AiNodeGetBool(node, "normalize"); + data->invert = AiNodeGetBool(node, "invert"); + data->trace_sets = AiNodeGetStr(node, "trace_sets"); + data->inclusive = AiNodeGetBool(node, "inclusive"); +} + +node_finish +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AiFree(data); +} + +shader_evaluate +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + + AtVector sample_dir; + switch (data->sample_direction) + { + case 0: + // Shading Normal + sample_dir = sg->N; + break; + case 1: + // Ray Direction + sample_dir = -sg->Rd; + break; + case 2: + // Custom Direction + sample_dir = data->custom_direction; + break; + default: + sample_dir = sg->N; + } + + + AiShaderGlobalsSetTraceSet(sg, data->trace_sets, data->inclusive); + AtRay ray = AiMakeRay(AI_RAY_DIFFUSE_REFLECT, sg->P, &sample_dir, AI_BIG, sg); + + // Sample Shading Color + if (data->sample_data_type == 11) { + sg->skip_shadow = true; + AtScrSample sample; + if (!AiTrace(ray, AI_RGB_WHITE, sample)) { + sg->out.RGB() = AiShaderEvalParamRGB(p_default_color); + return; + } + AtVector ray_dir = sample.point - sg->Ro; + AtRay color_ray = AiMakeRay(AI_RAY_DIFFUSE_REFLECT, sg->Ro, &ray_dir, AI_BIG, sg); + + AtScrSample color_sample; + if (!AiTrace(color_ray, AI_RGB_WHITE, color_sample)) { + sg->out.RGB() = AiShaderEvalParamRGB(p_default_color); + return; + } + sg->out.RGB() = color_sample.color; + sg->out.RGBA().a = 1.0; + return; + } + + AtShaderGlobals *hit_point = new AtShaderGlobals(*sg); + sg->skip_shadow = true; + + if (!AiTraceProbe(ray, hit_point)) { + sg->out.RGB() = AiShaderEvalParamRGB(p_default_color); + AiShaderGlobalsDestroy(hit_point); + return; + } + + AtVector vec; + AtNode *camera = AiUniverseGetCamera(); + AtMatrix world_to_camera_matrix; + AtMatrix world_to_screen_matrix; + AtMatrix world_to_tangent_matrix = AiM4Transpose(AiM4Frame(AtVector(), sg->dPdu, sg->dPdv, sg->N)); + AiWorldToCameraMatrix(camera, AiCameraGetShutterStart(), world_to_camera_matrix); + AiWorldToScreenMatrix(camera, AiCameraGetShutterStart(), world_to_screen_matrix); + switch (data->sample_data_type) + { + case 0: + vec = hit_point->N; + vec = (data->space == 1) ? AiShaderGlobalsTransformNormal(sg, vec, AI_WORLD_TO_OBJECT) : vec; + vec = (data->space == 2) ? AiM4VectorByMatrixMult(world_to_camera_matrix, vec) : vec; + vec = (data->space == 3) ? AiM4VectorByMatrixMult(world_to_screen_matrix, vec) : vec; + vec = (data->space == 4) ? AiM4VectorByMatrixMult(world_to_tangent_matrix, vec) : vec; + vec = (data->normalize) ? AiV3Normalize(vec) : vec; + vec = (data->invert) ? -1 * vec : vec; + break; + case 1: + vec = hit_point->Ns; + vec = (data->space == 1) ? AiShaderGlobalsTransformNormal(sg, vec, AI_WORLD_TO_OBJECT) : vec; + vec = (data->space == 2) ? AiM4VectorByMatrixMult(world_to_camera_matrix, vec) : vec; + vec = (data->space == 3) ? AiM4VectorByMatrixMult(world_to_screen_matrix, vec) : vec; + vec = (data->space == 4) ? AiM4VectorByMatrixMult(world_to_tangent_matrix, vec) : vec; + vec = (data->normalize) ? AiV3Normalize(vec) : vec; + vec = (data->invert) ? -1 * vec : vec; + break; + + case 2: + vec = hit_point->Ng; + vec = (data->space == 1) ? AiShaderGlobalsTransformNormal(sg, vec, AI_WORLD_TO_OBJECT) : vec; + vec = (data->space == 2) ? AiM4VectorByMatrixMult(world_to_camera_matrix, vec) : vec; + vec = (data->space == 3) ? AiM4VectorByMatrixMult(world_to_screen_matrix, vec) : vec; + vec = (data->space == 4) ? AiM4VectorByMatrixMult(world_to_tangent_matrix, vec) : vec; + vec = (data->normalize) ? AiV3Normalize(vec) : vec; + vec = (data->invert) ? -1 * vec : vec; + break; + + case 3: + vec = hit_point->Nf; + vec = (data->space == 1) ? AiShaderGlobalsTransformNormal(sg, vec, AI_WORLD_TO_OBJECT) : vec; + vec = (data->space == 2) ? AiM4VectorByMatrixMult(world_to_camera_matrix, vec) : vec; + vec = (data->space == 3) ? AiM4VectorByMatrixMult(world_to_screen_matrix, vec) : vec; + vec = (data->space == 4) ? AiM4VectorByMatrixMult(world_to_tangent_matrix, vec) : vec; + vec = (data->normalize) ? AiV3Normalize(vec) : vec; + vec = (data->invert) ? -1 * vec : vec; + break; + + case 4: + vec = hit_point->Ngf; + vec = (data->space == 1) ? AiShaderGlobalsTransformNormal(sg, vec, AI_WORLD_TO_OBJECT) : vec; + vec = (data->space == 2) ? AiM4VectorByMatrixMult(world_to_camera_matrix, vec) : vec; + vec = (data->space == 3) ? AiM4VectorByMatrixMult(world_to_screen_matrix, vec) : vec; + vec = (data->space == 4) ? AiM4VectorByMatrixMult(world_to_tangent_matrix, vec) : vec; + vec = (data->normalize) ? AiV3Normalize(vec) : vec; + vec = (data->invert) ? -1 * vec : vec; + break; + + case 5: + vec = hit_point->P; + vec = (data->space == 1) ? AiShaderGlobalsTransformPoint(sg, hit_point->Po, AI_WORLD_TO_OBJECT) : vec; + vec = (data->space == 2) ? AiM4PointByMatrixMult(world_to_camera_matrix, vec) : vec; + vec = (data->space == 3) ? AiM4PointByMatrixMult(world_to_screen_matrix, vec) : vec; + vec = (data->space == 4) ? AiM4PointByMatrixMult(world_to_tangent_matrix, vec) : vec; + vec = (data->invert) ? -1 * vec : vec; + break; + + case 6: + vec.x = hit_point->u; + vec.y = hit_point->v; + break; + + case 7: + vec = (data->normalize) ? AiV3Normalize(hit_point->dPdu) : hit_point->dPdu; + break; + + case 8: + vec = (data->normalize) ? AiV3Normalize(hit_point->dPdv) : hit_point->dPdv; + break; + + case 9: + AtVector binormal = AiV3Cross(hit_point->dPdu, hit_point->dPdv); + vec = (data->normalize) ? AiV3Normalize(binormal) : binormal; + vec = (data->invert) ? -1 * vec : vec; + break; + + case 10: + vec = hit_point->Rl; + vec = (data->normalize) ? AiV3Normalize(vec) : vec; + break; + + default: + AtRGB color = AiShaderEvalParamRGB(p_default_color); + vec.x = color.r; + vec.y = color.g; + vec.z = color.b; + break; + } + + sg->out.RGB().r = vec.x; + sg->out.RGB().g = vec.y; + sg->out.RGB().b = vec.z; + sg->out.RGBA().a = 1.0f; + AiShaderGlobalsDestroy(hit_point); +} +node_loader +{ + if (i > 0) + return false; + + node->methods = apSurfaceSample; + node->output_type = AI_TYPE_RGB; + node->name = "apSurfaceSample"; + node->node_type = AI_NODE_SHADER; + strcpy(node->version, AI_VERSION); + return true; +} diff --git a/src/apSurfaceSample/apSurfaceSample.mtd b/src/apSurfaceSample/apSurfaceSample.mtd new file mode 100644 index 0000000..d160677 --- /dev/null +++ b/src/apSurfaceSample/apSurfaceSample.mtd @@ -0,0 +1,43 @@ +[node apSurfaceSample] + maya.name STRING "apSurfaceSample" + maya.id INT 0x0005115 + maya.classification STRING "shader/texture" + +[attr default_color] + desc STRING "Default Color" + maya.keyable BOOL false + linkable BOOL true + +[attr sample_direction] + desc STRING "Sample Direction" + maya.keyable BOOL false + linkable BOOL true + +[attr custom_direction] + desc STRING "Custom Direction" + maya.keyable BOOL false + linkable BOOL true + +[attr sample_type] + desc STRING "Sample Type" + maya.keyable BOOL false + linkable BOOL false + +[attr normalize] + desc STRING "Normalize Output Vector" + maya.keyable BOOL false + linkable BOOL false +[attr invert] + desc STRING "Invert Output Vector" + maya.keyable BOOL false + linkable BOOL false +[attr trace_sets] + desc STRING "Trace Sets" + maya.keyable BOOL false + linkable BOOL false + +[attr inclusive] + desc STRING "Trace Set Inclusive" + maya.keyable BOOL false + linkable BOOL false + diff --git a/src/apSurfaceSample/apSurfaceSampleTemplate.py b/src/apSurfaceSample/apSurfaceSampleTemplate.py new file mode 100644 index 0000000..8d72506 --- /dev/null +++ b/src/apSurfaceSample/apSurfaceSampleTemplate.py @@ -0,0 +1,36 @@ +import maya.mel +from mtoa.ui.ae.shaderTemplate import ShaderAETemplate + +class AEapSurfaceSampleTemplate(ShaderAETemplate): + def setup(self): + self.addSwatch() + self.beginScrollLayout() + + self.beginLayout("Color", collapse=False) + self.addControl('default_color', label='Default Color', annotation='Default Color') + self.endLayout() + + self.beginLayout("Sample", collapse=False) + self.addControl('sample_direction', label='Sample Direction', annotation='Sample Direction') + self.addControl('custom_direction', label='Custom Direction', annotation='Custom Direction') + self.endLayout() + + self.beginLayout("Output", collapse=False) + self.addControl('sample_data_type', label='Sample Data Type', annotation='Sample Data Type') + self.beginNoOptimize() + self.addControl('space', label='Space', annotation='Normalize Output Vector') + self.addControl('normalize', label='Normalize', annotation='Normalize Output Vector') + self.addControl('invert', label='Invert', annotation='Invert Output Vector') + self.endNoOptimize() + self.endLayout() + + self.beginLayout("Render", collapse=False) + self.addControl('trace_sets', label='Trace Sets', annotation='Trace Sets') + self.addControl('inclusive', label='Inclusive', annotation='Inclusive') + self.endLayout() + + maya.mel.eval('AEdependNodeTemplate '+self.nodeName) + + self.addExtraControls() + self.endScrollLayout() + diff --git a/src/apTextureRandom/CMakeLists.txt b/src/apTextureRandom/CMakeLists.txt new file mode 100644 index 0000000..2336518 --- /dev/null +++ b/src/apTextureRandom/CMakeLists.txt @@ -0,0 +1,23 @@ +set(SHADER apTextureRandom) + +set(SRC_FILES + "apTextureRandom.cpp") + +set(META_FILES + "apTextureRandom.mtd") + +set(TEMPLATE_FILES + "apTextureRandomTemplate.py") + +include_directories(${ARNOLD_INCLUDE_PATH}) +add_library(${SHADER} SHARED ${SRC_FILES}) +set_target_properties(${SHADER} PROPERTIES PREFIX "") + +target_link_libraries(${SHADER} ${ARNOLD_AI_LIBRARY}) + +set(INSTALL_SHADER_TARGET "${CMAKE_INSTALL_PREFIX}/${ARNOLD_VERSION}/${CMAKE_PROJECT_NAME}/shaders") +set(INSTALL_TEMPLATE_TARGET "${CMAKE_INSTALL_PREFIX}/${ARNOLD_VERSION}/${CMAKE_PROJECT_NAME}/templates") + +install(TARGETS ${SHADER} RUNTIME DESTINATION ${INSTALL_SHADER_TARGET}) +install(FILES ${META_FILES} DESTINATION ${INSTALL_SHADER_TARGET}) +install(FILES ${TEMPLATE_FILES} DESTINATION ${INSTALL_TEMPLATE_TARGET}) \ No newline at end of file diff --git a/src/apTextureRandom/apTextureRandom.cpp b/src/apTextureRandom/apTextureRandom.cpp new file mode 100644 index 0000000..1667882 --- /dev/null +++ b/src/apTextureRandom/apTextureRandom.cpp @@ -0,0 +1,337 @@ +#include +#include +AI_SHADER_NODE_EXPORT_METHODS(apTextureRandom) + +inline void fast_sincos(float x, float* sine, float* cosine) +{ + +} + +inline void sincos(float x, float* sine, float* cosine) +{ + *sine = std::sin(x); + *cosine = std::cos(x); +} + +inline AtVector rotate(AtVector p, float angle, AtVector a, AtVector b) +{ + AtVector axis = AiV3Normalize(b - a); + float cosang, sinang; + sincos(angle, &cosang, &sinang); + float cosang1 = 1.0 - cosang; + float x = axis[0], y = axis[1], z = axis[2]; + AtMatrix matrix; + matrix[0][0] = x * x + (1.0 - x * x) * cosang; + matrix[0][1] = x * y * cosang1 + z * sinang; + matrix[0][2] = x * z * cosang1 - y * sinang; + matrix[0][3] = 0.0; + + matrix[1][0] = x * y * cosang1 - z * sinang; + matrix[1][1] = y * y + (1.0 - y * y) * cosang; + matrix[1][2] = y * z * cosang1 + x * sinang; + matrix[1][3] = 0.0; + + matrix[2][0] = x * z * cosang1 + y * sinang; + matrix[2][1] = y * z * cosang1 - x * sinang; + matrix[2][2] = z * z + (1.0 - z * z) * cosang; + matrix[2][3] = 0.0; + + matrix[3][0] = 0.0; + matrix[3][1] = 0.0; + matrix[3][2] = 0.0; + matrix[3][3] = 1.0; + return AiM4VectorByMatrixMult(matrix, p-a) + a; +} + +enum apTextureRandomParams +{ + p_default_color, + p_input_mode, + p_max_files, + p_file_path, + p_max_colors, + p_color0, + p_alpha0, + p_color1, + p_alpha1, + p_color2, + p_alpha2, + p_color3, + p_alpha3, + p_background, + p_background_alpha, + p_scale, + p_seed, + p_probability, + p_pos_random, + p_scale_min, + p_scale_max, + p_uniform_scale, + p_pixel_scale, + p_rotate_min, + p_rotate_max, + p_rotate_steps, + p_hsv_min, + p_hsv_max, + p_alpha_min, + p_alpha_max, + p_gamma_min, + p_gamma_max, + p_clamp, + p_auto_gamma, + p_manual_gamma, + p_overlap +}; + +static const char* InputModeNames[] = { + "Color", + "File Path", + NULL +}; + +struct ShaderData +{ + int input_mode; + int max_files; + std::string file_path; + int file_count; + int max_colors; + float scale; + int seed; + AtVector probability; + AtVector2 pos_random; + AtVector2 scale_min; + AtVector2 scale_max; + bool uniform_scale; + float pixel_scale; + float rotate_min; + float rotate_max; + int rotate_steps; + AtVector hsv_min; + AtVector hsv_max; + float alpha_min; + float alpha_max; + float gamma_min; + float gamma_max; + bool clamp; + bool auto_gamma; + float manual_gamma; + int overlap; +}; + +node_parameters +{ + AiParameterRGB("default_color", 0, 0, 0); + AiParameterEnum("input_mode", 0, InputModeNames); + + AiParameterInt("max_files", 0) + AiParameterStr("file_path", ""); + + AiParameterInt("max_colors", 4); + AiParameterRGB("color0", 1.0, 0, 0); + AiParameterFlt("alpha0", 1.0) + AiParameterRGB("color1", 1.0, 1.0, 0); + AiParameterFlt("alpha1", 1.0) + AiParameterRGB("color2", 0.0, 0, 1.0); + AiParameterFlt("alpha2", 1.0) + AiParameterRGB("color3", 1.0, 0, 1.0); + AiParameterFlt("alpha3", 1.0) + + AiParameterRGB("background", 0, 0, 0); + AiParameterFlt("background_alpha", 1.0); + AiParameterFlt("scale", 1.0); + AiParameterInt("seed", 39); + AiParameterVec("probability", 1.0, 0, 0.1); + AiParameterVec2("pos_random", 0.5, 0.5); + + AiParameterVec2("scale_min", 1.0, 1.0); + AiParameterVec2("scale_max", 1.0, 1.0); + AiParameterBool("uniform_scale", true); + AiParameterFlt("pixel_scale", 0.0); + + AiParameterFlt("rotate_min", 0); + AiParameterFlt("rotate_max", 0); + AiParameterInt("rotate_steps", 1); + + AiParameterVec("hsv_min", 0.0, 1.0, 1.0); + AiParameterVec("hsv_max", 0.0, 1.0, 1.0); + + AiParameterFlt("alpha_min", 1.0); + AiParameterFlt("alpha_max", 1.0); + + AiParameterFlt("gamma_min", 0.0); + AiParameterFlt("gamma_max", 0.0); + + AiParameterBool("clamp", true); + AiParameterBool("auto_gamma", true); + AiParameterFlt("manual_gamma", 1.0); + AiParameterInt("overlap", 1); +} + +node_initialize +{ + ShaderData *data = (ShaderData *)AiMalloc(sizeof(ShaderData)); + AiNodeSetLocalData(node, data); +} + +node_update +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + data->input_mode = AiNodeGetInt(node, "input_mode"); + data->file_path = AiNodeGetStr(node, "file_path").c_str(); + data->max_files = AiNodeGetInt(node, "max_files"); + data->max_colors = AiNodeGetInt(node, "max_colors"); + + if(data->input_mode == 0 && data->max_colors < 1) + data->max_colors = 1; + if(data->input_mode == 0 && data->max_colors > 4) + data->max_colors = 4; + + data->scale = AiNodeGetFlt(node, "scale"); + data->overlap = AiNodeGetInt(node, "overlap"); + data->seed = AiNodeGetInt(node, "seed"); + data->probability = AiNodeGetVec(node, "probability"); + data->pos_random = AiNodeGetVec2(node, "pos_random"); + data->pixel_scale = AiNodeGetFlt(node, "pixel_scale"); + data->scale_min = AiNodeGetVec2(node, "scale_min"); + data->scale_max = AiNodeGetVec2(node, "scale_max"); + data->uniform_scale = AiNodeGetBool(node, "uniform_scale"); + data->rotate_min = AiNodeGetFlt(node, "rotate_min"); + data->rotate_max = AiNodeGetFlt(node, "rotate_max"); + data->rotate_steps = AiNodeGetInt(node, "rotate_steps"); + +} + +node_finish +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AiFree(data); +} + +shader_evaluate +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + float scale = AiShaderEvalParamFlt(p_scale); + AtVector probability = AiShaderEvalParamVec(p_probability); + + float u = sg->u / scale; + float v = sg->v / scale; + + int ix = int(floor(u)); + int iy = int(floor(v)); + float fx = u - ix; + float fy = v - iy; + int max_files = data->max_files; + + //if(data->num_layers > 0 && noise) + int mod_value = (data->input_mode == 0) ? data->max_colors : data->max_files; + + float gamma = 1.0; + AtRGB output; + float alpha = 1.0; + AtRGB background = AiShaderEvalParamRGB(p_background); + float background_alpha = AiShaderEvalParamFlt(p_background_alpha); + output = background * background_alpha; + alpha = background_alpha; + for(int xx = -data->overlap; xx <= data->overlap; xx++) + { + for(int yy = -data->overlap; yy <= data->overlap; yy++) + { + AtVector rnd_point(ix + xx, iy + yy, data->seed); + // AtVector2 rnd_point(ix + xx, iy + yy); + rnd_point[0] = rnd_point[0] < 0 ? rnd_point[0]-1 : rnd_point[0]; + rnd_point[1] = rnd_point[1] < 0 ? rnd_point[1]-1 : rnd_point[1]; + rnd_point[2] = rnd_point[2] < 0 ? rnd_point[2]-1 : rnd_point[2]; + + // rnd_point[2] = rnd_point[2] < 0 ? rnd_point[2]-1 : rnd_point[2]; + AtVector pos = (AiVCellNoise4(rnd_point, 0) - AtVector(0.5, 0.5, 0)) * AtVector(data->pos_random[0], data->pos_random[1], 1.0); + AtVector lp = AtVector(fx-xx, fy-yy, 0) - pos; + + float prob = probability[0] + AiPerlin3(rnd_point * probability[2]) * probability[1]; + + if (pos[2] < prob) + { + AtVector scr = AiVCellNoise4(rnd_point, 1); + int pic = int((AiCellNoise4(rnd_point, 15) * 100)) % mod_value; + float sx = 1.0; + float sy = 1.0; + float scaleX = sx * AiLerp(scr[0], data->scale_min[0], data->scale_max[0]); + float scaleY = sy * AiLerp(scr[data->uniform_scale ? 0 : 1], data->scale_min[1], data->scale_max[1]); + if(data->rotate_steps > 1) + { + scr[2] = floor(scr[2]* data->rotate_steps) / (data->rotate_steps - 1); + } + float rot = AiLerp(scr[2], data->rotate_min, data->rotate_max); + lp -= 0.5; + float radians = rot*(AI_PI/180); + lp = rotate(lp, radians, AtVector(0, 0, 0), AtVector(0, 0, 1)); + lp /= AtVector(scaleX, scaleY, 1.0); + lp += 0.5; + if(lp.x >= 0 && lp.x <= 1.0 && lp.y >= 0 && lp.y <= 1.0) + { + float cache_u = sg->u; + float cache_v = sg->v; + + sg->u = lp.x; + sg->v = lp.y; + + AtRGB rgb; + float a = 1.0; + + if(pic == 0) + { + rgb = AiShaderEvalParamRGB(p_color0); + a = AiShaderEvalParamFlt(p_alpha0); + rgb *= a; + + }else if(pic == 1) + { + rgb = AiShaderEvalParamRGB(p_color1); + a = AiShaderEvalParamFlt(p_alpha1); + rgb *= a; + + }else if(pic == 2) + { + rgb = AiShaderEvalParamRGB(p_color2); + a = AiShaderEvalParamFlt(p_alpha2); + rgb *= a; + + }else if(pic == 3) + { + rgb = AiShaderEvalParamRGB(p_color3); + a = AiShaderEvalParamFlt(p_alpha3); + rgb *= a; + } + + if(a > 0.0) + { + + } + + alpha = 1.0 - ((1.0 - alpha)*(1.0-a)); + sg->u = cache_u; + sg->v = cache_v; + + AtRGB result = output * (1.0 - a) + rgb; + sg->out.RGBA().r = result.r; + sg->out.RGBA().g = result.g; + sg->out.RGBA().b = result.b; + sg->out.RGBA().a = alpha; + } + } + } + } +} + +node_loader +{ + if (i > 0) + return false; + + node->methods = apTextureRandom; + node->output_type = AI_TYPE_RGBA; + node->name = "apTextureRandom"; + node->node_type = AI_NODE_SHADER; + strcpy(node->version, AI_VERSION); + return true; +} \ No newline at end of file diff --git a/src/apTextureRandom/apTextureRandom.mtd b/src/apTextureRandom/apTextureRandom.mtd new file mode 100644 index 0000000..a3e4cc7 --- /dev/null +++ b/src/apTextureRandom/apTextureRandom.mtd @@ -0,0 +1,169 @@ +[node apTextureRandom] + maya.name STRING "apTextureRandom" + maya.id INT 0x0005120 + maya.classification STRING "shader/texture" + [attr default_color] + desc STRING "Default Color" + maya.keyable BOOL false + linkable BOOL true + + [attr num_layer] + desc STRING "Num of Layers" + maya.keyable BOOL false + linkable BOOL false + + [attr texture0] + desc STRING "Texture 0" + maya.keyable BOOL false + linkable BOOL true + + [attr alpha0] + desc STRING "Alpha 0" + maya.keyable BOOL false + linkable BOOL true + + [attr texture1] + desc STRING "Texture 1" + maya.keyable BOOL false + linkable BOOL true + + [attr alpha1] + desc STRING "Alpha 1" + maya.keyable BOOL false + linkable BOOL true + + [attr texture2] + desc STRING "Texture 2" + maya.keyable BOOL false + linkable BOOL true + + [attr alpha2] + desc STRING "Alpha 2" + maya.keyable BOOL false + linkable BOOL true + + [attr texture3] + desc STRING "Texture 3" + maya.keyable BOOL false + linkable BOOL true + + [attr alpha3] + desc STRING "Alpha 3" + maya.keyable BOOL false + linkable BOOL true + + [attr background] + desc STRING "Background" + maya.keyable BOOL false + linkable BOOL true + + [attr background_alpha] + desc STRING "Background Alpha" + maya.keyable BOOL false + linkable BOOL true + + [attr scale] + desc STRING "Scale" + maya.keyable BOOL false + linkable BOOL false + + [attr seed] + desc STRING "Seed" + maya.keyable BOOL false + linkable BOOL false + + [attr probability] + desc STRING "Probability" + maya.keyable BOOL false + linkable BOOL false + + [attr pos_random] + desc STRING "Position Random" + maya.keyable BOOL false + linkable BOOL false + + [attr scale_min] + desc STRING "Scale Min" + maya.keyable BOOL false + linkable BOOL false + + [attr scale_max] + desc STRING "Scale Max" + maya.keyable BOOL false + linkable BOOL false + + [attr uniform_scale] + desc STRING "Uniform Scale" + maya.keyable BOOL false + linkable BOOL false + + [attr pixel_scale] + desc STRING "Pixel Scale" + maya.keyable BOOL false + linkable BOOL false + + [attr rotate_min] + desc STRING "Rotate Min" + maya.keyable BOOL false + linkable BOOL false + + [attr rotate_max] + desc STRING "Rotate Max" + maya.keyable BOOL false + linkable BOOL false + + [attr rotate_steps] + desc STRING "Rotate Steps" + maya.keyable BOOL false + linkable BOOL false + + [attr hsv_min] + desc STRING "HSV Min" + maya.keyable BOOL false + linkable BOOL false + + [attr hsv_max] + desc STRING "HSV Max" + maya.keyable BOOL false + linkable BOOL false + + [attr alpha_min] + desc STRING "Alpha Min" + maya.keyable BOOL false + linkable BOOL false + + [attr alpha_max] + desc STRING "Alpha Max" + maya.keyable BOOL false + linkable BOOL false + + [attr gamma_min] + desc STRING "Gamma Min" + maya.keyable BOOL false + linkable BOOL false + + [attr gamma_max] + desc STRING "Gamma Max" + maya.keyable BOOL false + linkable BOOL false + + [attr clamp] + desc STRING "Clamp" + maya.keyable BOOL false + linkable BOOL false + + [attr auto_gamma] + desc STRING "Auto Gamma" + maya.keyable BOOL false + linkable BOOL false + + [attr manual_gamma] + desc STRING "Manual Gamma" + maya.keyable BOOL false + linkable BOOL false + + [attr overlap] + desc STRING "Overlap" + maya.keyable BOOL false + linkable BOOL false + diff --git a/src/apTextureRandom/apTextureRandomTemplate.py b/src/apTextureRandom/apTextureRandomTemplate.py new file mode 100644 index 0000000..d143ac8 --- /dev/null +++ b/src/apTextureRandom/apTextureRandomTemplate.py @@ -0,0 +1,56 @@ +import maya.mel +from mtoa.ui.ae.shaderTemplate import ShaderAETemplate + +class AEapTextureRandomTemplate(ShaderAETemplate): + def setup(self): + self.addSwatch() + self.beginScrollLayout() + self.beginLayout('Color', collapse=False) + self.addControl('default_color', label='Default Color', annotation='Default Color') + self.addControl('background', label='Background', annotation='Background Color') + self.addControl('background_alpha', label='Background Alpha', annotation='Background Color') + self.endLayout() + + self.beginLayout("Inputs", collapse=False) + self.addControl('num_layer', label='Num of Layers', annotation='Number of Layer for Randomized') + self.addControl('color0', label='Color 0', annotation='Color Input 0') + self.addControl('alpha0', label='Alpha 0', annotation='Alpha Input 0') + self.addControl('color1', label='Color 1', annotation='Color Input 1') + self.addControl('alpha1', label='Alpha 1', annotation='Alpha Input 1') + self.addControl('color2', label='Color 2', annotation='Color Input 2') + self.addControl('alpha2', label='Alpha 2', annotation='Alpha Input 2') + self.addControl('color3', label='Color 3', annotation='Color Input 3') + self.addControl('alpha3', label='Alpha 3', annotation='Alpha Input 3') + self.endLayout() + + self.beginLayout('Randomize Controls', collapse=False) + self.addControl('scale', label='Scale', annotation='UV Scale') + self.addControl('seed', label='Seed', annotation='Random Seed') + self.addControl('probability', label='Probability', annotation='Probability of distribution') + self.addControl('pos_random', label='Position', annotation='Position Random') + self.addControl('scale_min', label='Scale Min', annotation='Scale Minimum Value') + self.addControl('scale_max', label='Scale Max', annotation='Scale Maximum Value') + self.addControl('uniform_scale', label='Uniform Scale', annotation='Uniform Scale') + # self.addControl('pixel_scale', label='Pixel Scale', annotation='Pixel Scale') + self.addControl('rotate_min', label='Rotate Min', annotation='Rotate Minimum Value') + self.addControl('rotate_max', label='Rotate Max', annotation='Rotate Maximum Value') + self.addControl('rotate_step', label='Rotate Step', annotation='Rotate Step') + self.addControl('overlap', label='Overlap', annotation='Overlap') + self.endLayout() + + self.beginLayout('Color Randomize', collapse=False) + self.addControl('hsv_min', label='HSV Min', annotation='Minimum HSV Value') + self.addControl('hsv_max', label='HSV Max', annotation='Maximum HSV Value') + self.addControl('alpha_min', label='Alpha Min', annotation='Minimum Alpha Value') + self.addControl('alpha_max', label='Alpha Max', annotation='Maximum Alpha Value') + self.addControl('gamma_min', label='Gamma Min', annotation='Minimum Gamma Value') + self.addControl('gamma_max', label='Gamma Max', annotation='Maximum Gamma Value') + self.addControl('auto_gamma', label='Auto Gamma', annotation='Auto Gamma (Input Mode:File Only)') + self.addControl('manual_gamma', label='Manual Gamma', annotation='Manual Gamma Value') + self.addControl('clamp', label='Clamp', annotation='Clamp Max Value to 1'); + + self.endLayout() + + maya.mel.eval('AEdependNodeTemplate '+self.nodeName) + self.addExtraControls() + self.endScrollLayout() \ No newline at end of file diff --git a/src/apUvRange/CMakeLists.txt b/src/apUvRange/CMakeLists.txt new file mode 100644 index 0000000..b4500e2 --- /dev/null +++ b/src/apUvRange/CMakeLists.txt @@ -0,0 +1,23 @@ +set(SHADER apUvRange) + +set(SRC_FILES + "apUvRange.cpp") + +set(META_FILES + "apUvRange.mtd") + +set(TEMPLATE_FILES + "apUvRangeTemplate.py") + +include_directories(${ARNOLD_INCLUDE_PATH}) +add_library(${SHADER} SHARED ${SRC_FILES}) +set_target_properties(${SHADER} PROPERTIES PREFIX "") + +target_link_libraries(${SHADER} ${ARNOLD_AI_LIBRARY}) + +set(INSTALL_SHADER_TARGET "${CMAKE_INSTALL_PREFIX}/${ARNOLD_VERSION}/${CMAKE_PROJECT_NAME}/shaders") +set(INSTALL_TEMPLATE_TARGET "${CMAKE_INSTALL_PREFIX}/${ARNOLD_VERSION}/${CMAKE_PROJECT_NAME}/templates") + +install(TARGETS ${SHADER} RUNTIME DESTINATION ${INSTALL_SHADER_TARGET}) +install(FILES ${META_FILES} DESTINATION ${INSTALL_SHADER_TARGET}) +install(FILES ${TEMPLATE_FILES} DESTINATION ${INSTALL_TEMPLATE_TARGET}) \ No newline at end of file diff --git a/src/apUvRange/apUvRange.cpp b/src/apUvRange/apUvRange.cpp new file mode 100644 index 0000000..85d1b7c --- /dev/null +++ b/src/apUvRange/apUvRange.cpp @@ -0,0 +1,82 @@ +#include "ai.h" +#include + +AI_SHADER_NODE_EXPORT_METHODS(apUvRange) + +enum apUvRangeParams { + p_umin, + p_umax, + p_vmin, + p_vmax, + p_in_color, + p_out_color +}; + +struct ShaderData +{ + float umin; + float umax; + float vmin; + float vmax; + AtRGB in_range; + AtRGB out_range; +}; + +node_parameters +{ + AiParameterFlt("u_min", 0.0); + AiParameterFlt("u_max", 1.0); + AiParameterFlt("v_min", 0.0); + AiParameterFlt("v_max", 1.0); + AiParameterRGB("in_range", 1.0, 0, 0); + AiParameterRGB("out_range", 0, 1.0, 0); +} + +node_initialize +{ + ShaderData *data = (ShaderData*) AiMalloc(sizeof(ShaderData)); + AiNodeSetLocalData(node, data); +} + +node_update +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + data->umin = AiNodeGetFlt(node, "u_min"); + data->umax = AiNodeGetFlt(node, "u_max"); + data->vmin = AiNodeGetFlt(node, "v_min"); + data->vmax = AiNodeGetFlt(node, "v_max"); + data->in_range = AiNodeGetRGB(node, "in_range"); + data->out_range = AiNodeGetRGB(node, "out_range"); + data->umin = AiNodeGetFlt(node, "u_min"); +} +node_finish +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AiFree(data); +} + +shader_evaluate +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + if (sg->u >= data->umin && sg->u <= data->umax && + sg->v >= data->vmin && sg->v <= data->umax) + { + sg->out.RGB() = data->in_range; + return; + } + sg->out.RGB() = data->out_range; + return; +} + +node_loader +{ + if (i > 0) + return false; + + node->methods = apUvRange; + node->output_type = AI_TYPE_RGBA; + node->name = "apUvRange"; + node->node_type = AI_NODE_SHADER; + strcpy(node->version, AI_VERSION); + return true; +} \ No newline at end of file diff --git a/src/apUvRange/apUvRange.mtd b/src/apUvRange/apUvRange.mtd new file mode 100644 index 0000000..7ac4a00 --- /dev/null +++ b/src/apUvRange/apUvRange.mtd @@ -0,0 +1,34 @@ +[node apUvRange] + maya.name STRING "apUvRange" + maya.id INT 0x0005103 + maya.classification STRING "shader/utility" + [attr u_min] + desc STRING "U Min" + maya.keyable BOOL false + linkable BOOL true + + [attr u_max] + desc STRING "U Max" + maya.keyable BOOL false + linkable BOOL true + + [attr v_min] + desc STRING "V Min" + maya.keyable BOOL false + linkable BOOL true + + [attr v_max] + desc STRING "V Max" + maya.keyable BOOL false + linkable BOOL true + + [attr in_range] + desc STRING "In UV Range Color" + maya.keyable BOOL false + linkable BOOL true + + [attr out_range] + desc STRING "Out UV Range Color" + maya.keyable BOOL false + linkable BOOL true + diff --git a/src/apUvRange/apUvRangeTemplate.py b/src/apUvRange/apUvRangeTemplate.py new file mode 100644 index 0000000..e69de29 diff --git a/src/apVolume/Color.cpp b/src/apVolume/Color.cpp new file mode 100644 index 0000000..164826a --- /dev/null +++ b/src/apVolume/Color.cpp @@ -0,0 +1,88 @@ +#include "Color.h" + +inline AtVector2 point2(float x, float y) +{ + AtVector2 r; + r.x = x; + r.y = y; + return r; +} + +AtVector2 illumC(point2(0.3101, 0.3162)); +AtVector2 illumD65(point2(0.3127, 0.3291)); +AtVector2 illumE(point2(0.33333333, 0.33333333)); + +ColorSystem CsNTSC("NTSC", point2(0.67, 0.33), point2(0.21, 0.71), point2(0.14, 0.08), illumC); +ColorSystem CsSMPTE("SMPTE", point2(0.630, 0.340), point2(0.31, 0.595), point2(0.155, 0.07), illumD65); +ColorSystem CsHDTV("HDTV", point2(0.670, 0.330), point2(0.21, 0.71), point2(0.150, 0.06), illumD65); +ColorSystem CsCIE("CIE", point2(0.7355, 0.2645), point2(0.2658, 0.7243), point2(0.1669, 0.085), illumE); +ColorSystem CsRec709("Rec709", point2(0.64, 0.33), point2(0.30, 0.60), point2(0.15, 0.06), illumD65); + +float cieMatch[81][3] = +{ + { 0.0014,0.0000,0.0065 },{ 0.0022,0.0001,0.0105 },{ 0.0042,0.0001,0.0201 }, + { 0.0076,0.0002,0.0362 },{ 0.0143,0.0004,0.0679 },{ 0.0232,0.0006,0.1102 }, + { 0.0435,0.0012,0.2074 },{ 0.0776,0.0022,0.3713 },{ 0.1344,0.0040,0.6456 }, + { 0.2148,0.0073,1.0391 },{ 0.2839,0.0116,1.3856 },{ 0.3285,0.0168,1.6230 }, + { 0.3483,0.0230,1.7471 },{ 0.3481,0.0298,1.7826 },{ 0.3362,0.0380,1.7721 }, + { 0.3187,0.0480,1.7441 },{ 0.2908,0.0600,1.6692 },{ 0.2511,0.0739,1.5281 }, + { 0.1954,0.0910,1.2876 },{ 0.1421,0.1126,1.0419 },{ 0.0956,0.1390,0.8130 }, + { 0.0580,0.1693,0.6162 },{ 0.0320,0.2080,0.4652 },{ 0.0147,0.2586,0.3533 }, + { 0.0049,0.3230,0.2720 },{ 0.0024,0.4073,0.2123 },{ 0.0093,0.5030,0.1582 }, + { 0.0291,0.6082,0.1117 },{ 0.0633,0.7100,0.0782 },{ 0.1096,0.7932,0.0573 }, + { 0.1655,0.8620,0.0422 },{ 0.2257,0.9149,0.0298 },{ 0.2904,0.9540,0.0203 }, + { 0.3597,0.9803,0.0134 },{ 0.4334,0.9950,0.0087 },{ 0.5121,1.0000,0.0057 }, + { 0.5945,0.9950,0.0039 },{ 0.6784,0.9786,0.0027 },{ 0.7621,0.9520,0.0021 }, + { 0.8425,0.9154,0.0018 },{ 0.9163,0.8700,0.0017 },{ 0.9786,0.8163,0.0014 }, + { 1.0263,0.7570,0.0011 },{ 1.0567,0.6949,0.0010 },{ 1.0622,0.6310,0.0008 }, + { 1.0456,0.5668,0.0006 },{ 1.0026,0.5030,0.0003 },{ 0.9384,0.4412,0.0002 }, + { 0.8544,0.3810,0.0002 },{ 0.7514,0.3210,0.0001 },{ 0.6424,0.2650,0.0000 }, + { 0.5419,0.2170,0.0000 },{ 0.4479,0.1750,0.0000 },{ 0.3608,0.1382,0.0000 }, + { 0.2835,0.1070,0.0000 },{ 0.2187,0.0816,0.0000 },{ 0.1649,0.0610,0.0000 }, + { 0.1212,0.0446,0.0000 },{ 0.0874,0.0320,0.0000 },{ 0.0636,0.0232,0.0000 }, + { 0.0468,0.0170,0.0000 },{ 0.0329,0.0119,0.0000 },{ 0.0227,0.0082,0.0000 }, + { 0.0158,0.0057,0.0000 },{ 0.0114,0.0041,0.0000 },{ 0.0081,0.0029,0.0000 }, + { 0.0058,0.0021,0.0000 },{ 0.0041,0.0015,0.0000 },{ 0.0029,0.0010,0.0000 }, + { 0.0020,0.0007,0.0000 },{ 0.0014,0.0005,0.0000 },{ 0.0010,0.0004,0.0000 }, + { 0.0007,0.0002,0.0000 },{ 0.0005,0.0002,0.0000 },{ 0.0003,0.0001,0.0000 }, + { 0.0002,0.0001,0.0000 },{ 0.0002,0.0001,0.0000 },{ 0.0001,0.0000,0.0000 }, + { 0.0001,0.0000,0.0000 },{ 0.0001,0.0000,0.0000 },{ 0.0000,0.0000,0.0000 } +}; + +AtRGB xyzToRgb(const ColorSystem& cs, const AtRGB& xyz) +{ + float xr, yr, zr, xg, yg, zg, xb, yb, zb; + float xw, yw, zw; + float rx, ry, rz, gx, gy, gz, bx, by, bz; + float rw, gw, bw; + AtRGB rgb; + + xr = cs.red.x; yr = cs.red.y; zr = 1 - (xr + yr); + xg = cs.green.x; yg = cs.green.y; zg = 1 - (xg + yg); + xb = cs.blue.x; yb = cs.blue.y; zb = 1 - (xb + yb); + + xw = cs.white.x; yw = cs.white.y; zw = 1 - (xw + yw); + + // xyz -> rgb matrix, before scaling to white + rx = (yg * zb) - (yb * zg); ry = (xb * zg) - (xg * zb); rz = (xg * yb) - (xb * yg); + gx = (yb * zr) - (yr * zb); gy = (xr * zb) - (xb * zr); gz = (xb * yr) - (xr * yb); + bx = (yr * zg) - (yg * zr); by = (xg * zr) - (xr * zg); bz = (xr * yg) - (xg * yr); + + // White scaling factors. + // Dividing by yw scales the white luminance to unity, as conventional + rw = ((rx * xw) + (ry * yw) + (rz * zw)) / yw; + gw = ((gx * xw) + (gy * yw) + (gz * zw)) / yw; + bw = ((bx * xw) + (by * yw) + (bz * zw)) / yw; + + // xyz -> rgb matrix, correctly scaled to white + rx = rx / rw; ry = ry / rw; rz = rz / rw; + gx = gx / gw; gy = gy / gw; gz = gz / gw; + bx = bx / bw; by = by / bw; bz = bz / bw; + + // rgb of the desired point + rgb.r = (rx * xyz.r) + (ry * xyz.g) + (rz * xyz.b); + rgb.g = (gx * xyz.r) + (gy * xyz.g) + (gz * xyz.b); + rgb.b = (bx * xyz.r) + (by * xyz.g) + (bz * xyz.b); + + return rgb; +} \ No newline at end of file diff --git a/src/apVolume/Color.h b/src/apVolume/Color.h new file mode 100644 index 0000000..a3ceecb --- /dev/null +++ b/src/apVolume/Color.h @@ -0,0 +1,84 @@ +#pragma once + +#include +#include + +/// A structure representing a color coordinate system +struct ColorSystem +{ + ColorSystem(const std::string& name_, const AtVector2& r, const AtVector2& g, const AtVector2& b, const AtVector2& w) : + name(name_), red(r), green(g), blue(b), white(w) + {} + + std::string name; /// name of the system, e.g. rec709, ACES etc + AtVector2 red; /// chromaticity of the red primary + AtVector2 green; /// chromaticity of the green primary + AtVector2 blue; /// chromticity of the blue primary + AtVector2 white; /// chromaticity of the white point +}; + +/// White points for common illuminants +extern AtVector2 illumC; +extern AtVector2 illumD65; +extern AtVector2 illumE; + +/// Color system definitions for common color spaces +extern ColorSystem CsNTSC; +extern ColorSystem CsSMPTE; +extern ColorSystem CsHDTV; +extern ColorSystem CsCIE; +extern ColorSystem CsRec709; + +/// CIE spectral color matching functions from 380 to 780 nm, in 5nm increments +extern float cieMatch[81][3]; + +/// Function to convert a spectral intensity to CIE XYZ. The template argument SpecFunc should be a functor that +/// descrbes the desired spectral function. The functor should have the member: +/// AtFloat operator(const AtFloat wavelength) +/// which should return the spectral intensity of the function at the given wavelength +template +AtRGB spectrumToXyz(const SpecFunc& sf) +{ + AtRGB result; + float lambda = 380.0f; + float X = 0.0f, Y = 0.0f, Z = 0.0f; + for (int i = 0; lambda < 780.1; i++, lambda += 5) + { + double Me; + + Me = sf(lambda); + X += Me * cieMatch[i][0]; + Y += Me * cieMatch[i][1]; + Z += Me * cieMatch[i][2]; + } + float XYZ = (X + Y + Z); + + result.r = X / XYZ; + result.g = Y / XYZ; + result.b = Z / XYZ; + + return result; +} + +/// Function to convert an XYZ color to RGB +AtRGB xyzToRgb(const ColorSystem& cs, const AtRGB& xyz); + +/// Blackbody spectrum +struct BlackbodySpectrum +{ + BlackbodySpectrum(const float temperature) + : temp(temperature) + {} + + BlackbodySpectrum() + : temp(0.0f) + {} + + float operator()(float wavelength) const + { + double lambda = wavelength * 1e-9; + return (3.74183e-16 * pow(lambda, -5.0)) / (exp(1.4388e-2 / (lambda * temp)) - 1.0); + } + + double temp; +}; diff --git a/src/apVolume/VolumeCache.cpp b/src/apVolume/VolumeCache.cpp new file mode 100644 index 0000000..18d2e44 --- /dev/null +++ b/src/apVolume/VolumeCache.cpp @@ -0,0 +1,348 @@ +#include "VolumeCache.h" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + + +CacheInstance::CacheInstance() + : m_Valid(false) +{} + +CacheInstance::~CacheInstance() {} + +//OpenVDBCacheInstance::FloatGridSamplerPtr OpenVDBCacheInstance::_gridSampler; + +OpenVDBCacheInstance::OpenVDBCacheInstance(VolumeCache::Handle h, openvdb::GridBase::Ptr grid) + : m_Grid(grid), m_Handle(h) +{ + m_Valid = true; + m_CacheType = kOpenVDB; +} +template +auto OpenVDBCacheInstance::sample(int interpolation, const Imath::V3d& wsP) const -> typename GridType::ValueType +{ + using namespace openvdb::tools; + using Result = GridType::ValueType; + GridType::Ptr grid = openvdb::gridConstPtrCast(m_Grid); + auto accessor = grid->getAccessor(); + auto transform = m_Grid->transform(); + + openvdb::Vec3d sample_point(wsP.x, wsP.y, wsP.z); + auto index_point = m_Grid->worldToIndex(sample_point); + Result result = openvdb::zeroVal(); + switch (interpolation) + { + case Interpolation::kClosest: + PointSampler::sample(accessor, index_point, result); + break; + case Interpolation::kTriliear: + BoxSampler::sample(accessor, index_point, result); + break; + case Interpolation::kTricubic: + QuadraticSampler::sample(accessor, index_point, result); + break; + } + return result +} + +template +void OpenVDBCacheInstance::march_extents(const AtVolumeIntersectionInfo * info, const Ray & ray, const Intersector * master_intersector) +{ + Intersector intersector(*master_intersector); + + if (intersector.setWorldRay(ray)) + { + Intersector::RealType t_min, t_max; + while (intersector.march(t_min, t_max)) + { + const auto near_pos = intersector.getWorldPos(t_min); + const auto far_pos = intersector.getWorldPos(t_max); + + t_min = (near_pos - ray.eye()).length(); + t_max = (far_pos - ray.eye()).length(); + + AiVolumeAddIntersection(info, t_min, t_max); + } + } +} + +void OpenVDBCacheInstance::bounds(Imath::V3d& bbmin, Imath::V3d& bbmax) const +{ + openvdb::CoordBBox bbox = m_Grid->evalActiveVoxelBoundingBox(); + openvdb::Vec3d mn = bbox.min().asVec3d(); + openvdb::Vec3d mx = bbox.max().asVec3d(); + mn = m_Grid->indexToWorld(mn); + mx = m_Grid->indexToWorld(mx); + bbmin = Imath::V3d(mn.x(), mn.y(), mn.z()); + bbmax = Imath::V3d(mx.x(), mx.y(), mx.z()); +} + +size_t OpenVDBCacheInstance::memUsage() const +{ + return m_Grid->memUsage(); +} + +Imath::V3d OpenVDBCacheInstance::voxelSize() const +{ + openvdb::Vec3d v = m_Grid->voxelSize(); + return Imath::V3d(v.x(), v.y(), v.z()); +} + +VolumeCache::StaticInit VolumeCache::m_StaticInit; +VolumeCache* VolumeCache::m_Instance(0); +VolumeCache::StaticInit::StaticInit() +{ + openvdb::initialize(); +} + +VolumeCache* VolumeCache::instance() +{ + if (!m_Instance) + { + boost::mutex::scoped_lock m; + if (!m_Instance) + { + m_Instance = new VolumeCache; + } + } + return m_Instance; +} + +CacheInstance::Ptr VolumeCache::getCacheInstance(Handle h) +{ + CacheInstance::Ptr c; + if (h >= 0) + { + CacheInstanceMap::iterator it = m_CacheInstanceMap.find(h); + if (it != m_CacheInstanceMap.end()) + { + c = it->second; + } + } + + return c; +} + +VolumeCache::Handle VolumeCache::readField(const std::string& filename, const std::string& fieldName, bool openToNanoVDB = false) +{ + Handle h; + + boost::mutex::scoped_lock lock; + + // check in our cache entries to see if we've loaded this cache already + std::string fileHandle = filename + std::string("/") + fieldName; + FileHandleMap::const_iterator it = m_FileHandleMap.find(fileHandle); + if (it != m_FileHandleMap.end()) + { + // just return the existing handle + h = it->second; + } + else + { + // try and load it + // first figure out what type of file we have + // std::string ext = cacheName.substr(cacheName.length() - 3, std::string::npos); + std::string ext = filename.substr(filename.find_last_of(".") + 1); + + if (ext == "vdb") + { + h = readOpenVDBGrid(filename, fieldName, false); + m_FileHandleMap[fileHandle] = h; + } + else if (ext == "nvdb") + { + h = readNanoVDBGrid(filename, fieldName, false); + m_FileHandleMap[fileHandle] = h; + } + else if (ext == "f3d") + { + + } + else + { + std::cerr << "[VolumeCache] Unsupported file type with extension '" << ext << "'" << std::endl; + } + } + + return h; +} + +void VolumeCache::evict(Handle h) +{ + CacheInstanceMap::iterator it = m_CacheInstanceMap.find(h); + if (it != m_CacheInstanceMap.end()) m_CacheInstanceMap.erase(it); +} + +size_t VolumeCache::memUsage() const +{ + CacheInstanceMap::const_iterator it = m_CacheInstanceMap.begin(); + size_t mem = 0; + for (; it != m_CacheInstanceMap.end(); ++it) + { + mem += it->second->memUsage(); + } + return mem; +} + +VolumeCache::Handle VolumeCache::readOpenVDBGrid(const std::string& filename, const std::string& gridName, bool opentoNanoVDB = false) +{ + VolumeCache::Handle h; + try + { + openvdb::io::File file(filename); + file.open(); + openvdb::GridBase::Ptr gridBase = file.readGrid(gridName); + file.close(); + if (gridBase) + { + h = m_NumEntries++; + OpenVDBCacheInstance::Ptr oc(new OpenVDBCacheInstance(h, gridBase)); + m_CacheInstanceMap[h] = oc; + } + else + { + h = -1; + } + } + catch (openvdb::Exception& e) + { + std::cerr << "[VolumeCache] " << e.what() << std::endl; + h = kInvalidFile; + } + + return h; +} + +VolumeCache::Handle VolumeCache::readNanoVDBGrid(const std::string & filename, const std::string & gridName, bool openToOpenVDB) +{ + VolumeCache::Handle h; + + auto gridHandle = nanovdb::io::readGrid<>(filename); + + if (gridHandle) + { + h = m_NumEntries++; + NanoVDBCacheInstance::Ptr nc(new NanoVDBCacheInstance(h, std::move(gridHandle))); + m_CacheInstanceMap[h] = nc; + } + else + { + h = -1; + } + + return h; +} + +NanoVDBCacheInstance::NanoVDBCacheInstance(VolumeCache::Handle h, nanovdb::GridHandle<> gridHandle) + :m_Handle(h), m_GridHandle(&gridHandle) +{ +} + +bool NanoVDBCacheInstance::march_extents(const AtVolumeIntersectionInfo* info, const Imath::V3f &ray_origin, const Imath::V3f &ray_direction, float t0, float t1) +{ + nanovdb::Vec3f ray_eye(ray_origin.x, ray_origin.y, ray_origin.z); + nanovdb::Vec3f ray_dir(ray_direction.x, ray_direction.y, ray_direction.z); + const nanovdb::Ray ray(ray_eye, ray_dir, t0, t1); + + const auto grid = m_GridHandle->grid(); + const auto& tree = grid->tree(); + auto grid_accessor = tree.getAccessor(); + auto index_ray = ray.worldToIndexF(*grid); + + nanovdb::TreeMarcher::LeafNodeType, nanovdb::Ray, decltype(grid_accessor)> marcher(grid_accessor); + + if (!marcher.init(index_ray)) + return false; + + const typename nanovdb::NanoTree::LeafNodeType* node = nullptr; + float t_min, t_max; + while (marcher.step(&node, t_min, t_max)) + { + const auto near_pos = index_ray.indexToWorldF(*grid)(t_min); + const auto far_pos = index_ray.indexToWorldF(*grid)(t_max); + t_min = (near_pos - ray.eye()).length(); + t_max = (far_pos - ray.eye()).length(); + AiVolumeAddIntersection(info, t_min, t_max); + } +} + +void NanoVDBCacheInstance::bounds(Imath::V3d & bbmin, Imath::V3d & bbmax) const +{ + auto worldBBox = m_GridHandle->gridMetaData()->worldBBox(); + bbmin.x = worldBBox.min()[0]; + bbmin.y = worldBBox.min()[1]; + bbmin.z = worldBBox.min()[2]; + bbmax.x = worldBBox.max()[0]; + bbmax.y = worldBBox.max()[1]; + bbmax.z = worldBBox.max()[2]; +} + +size_t NanoVDBCacheInstance::memUsage() const +{ + size_t memUsage; + + switch (m_GridHandle->gridMetaData()->gridType()) + { + case nanovdb::GridType::Float: + memUsage = m_GridHandle->grid()->memUsage(); + break; + case nanovdb::GridType::Vec3f: + memUsage = m_GridHandle->grid()->memUsage(); + break; + } + return memUsage; +} + +Imath::V3d NanoVDBCacheInstance::voxelSize() const +{ + auto voxelSize = m_GridHandle->gridMetaData()->voxelSize(); + return Imath::V3d(voxelSize[0], voxelSize[1], voxelSize[2]); +} + +template +auto NanoVDBCacheInstance::sample(int interpolation, const Imath::V3d& wsP) const -> typename GridType +{ + auto grid = m_GridHandle->grid(); + auto& grid_tree = grid->tree(); + auto grid_accessor = grid_tree.getAccessor(); + + nanovdb::Vec3f sample_point(wsP.x, wsP.y, wsP.z); + // Transform sample point from object space to world space + auto world_point = grid->map().applyInverseMap(sample_point); + + auto index_point = grid->worldToIndexF(world_point); + + GridType result; + + switch (interpolation) + { + case Interpolation::kClosest: + { + auto sampler = nanovdb::createSampler<0, decltype(grid_accessor), false>(grid_accessor); + result = sampler(index_point); + break; + } + case Interpolation::kTriliear: + { + auto sampler = nanovdb::createSampler<1, decltype(grid_accessor), false>(grid_accessor); + result = sampler(index_point); + break; + } + case Interpolation::kTricubic: + + auto sampler = nanovdb::createSampler<2, decltype(grid_accessor), false>(grid_accessor); + result = sampler(index_point); + break; + } + return result; +} \ No newline at end of file diff --git a/src/apVolume/VolumeCache.h b/src/apVolume/VolumeCache.h new file mode 100644 index 0000000..26c653e --- /dev/null +++ b/src/apVolume/VolumeCache.h @@ -0,0 +1,185 @@ +#pragma once + +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#include + +// some useful shorthands +typedef openvdb::FloatGrid FloatGridType; +typedef FloatGridType::TreeType FloatGridTreeType; + +typedef openvdb::Vec3SGrid Vec3SGridType; +typedef Vec3SGridType::TreeType Vec3SGridTreeType; + +/// Abstract base class for cache instances. One CacheInstance represents a single layer from a Field3D or OpenVDB cache +class CacheInstance +{ +public: + enum CacheType + { + kField3D = 0, + kOpenVDB + }; + enum Interpolation + { + kClosest = 0, + kTriliear, + kTricubic + }; + CacheInstance(); + virtual ~CacheInstance(); + + /// Lookup an interpolated value from the cache + /// @param wsP The world-space position to look up + /// @return The field value at @wsP + + //virtual void* lookup(const Imath::V3d& wsP) const = 0; + + /// Get the world-space bounding-box of the field + /// @param Bounding box minimum + /// @param Bounding box maximum + virtual void bounds(Imath::V3d& bbmin, Imath::V3d& bbmax) const = 0; + /// Is the cache valid or not? + inline bool valid() const { return m_Valid; } + /// What type is the cache (either kField3D or kOpenVDB) + inline CacheType cacheType() const { return m_CacheType; } + /// How much memory is this CacheInstance using? + virtual size_t memUsage() const = 0; + /// How big are the voxels? + virtual Imath::V3d voxelSize() const = 0; + + typedef boost::shared_ptr Ptr; + +protected: + bool m_Valid; + CacheType m_CacheType; +}; + + + +/// The VolumeCache object manages loading particular layers from cache files and managing their lifetime in memory. +/// To use it callers should use VolumeCache::instance() to get the singleton instance, then call readFloatField() to read a layer from a cache +/// into memory. This returns a Handle object that can be used to get the actual CacheInstance object that stores the layer. If the returned +/// handle is less than 0 then something went wrong loading the layer. Attempting to get a CacheInstance from such a Handle will return a null +/// pointer. +class VolumeCache +{ +public: + /// Handle for accessing loaded volume cache data + typedef int Handle; + static const int kInvalidFile = -1; + static const int kInvalidField = -2; + static const int kInvalidFieldType = -3; + static const int kUnknownError = -9; + + enum FilterType + { + kFast = 0, + kLinear, + kSmooth + }; + + /// Get the volume cache manager singleton + static VolumeCache* instance(); + + /// Read a float field/grid from the given volume file + /// @return A handle for accessing the grid data. If the read failed the returned Handle will have value < 0 + /// @param cacheName Path to the Field3D or OpenVDB file to read + /// @param fieldName Name of the field in the cache to read + Handle readField(const std::string& cacheName, const std::string& fieldName, bool openToNanoVDB); + + /// Evict a loaded field from memory. The object will be destroyed after any remaining Ptrs held by the caller are destroyed + void evict(Handle h); + + /// Report the total size, in bytes, of the memory used by caches currently loaded + size_t memUsage() const; + + /// Return the CacheInstance for the given Handle + CacheInstance::Ptr getCacheInstance(Handle h); + bool m_Initialized = false; + +private: + VolumeCache() : m_NumEntries(0) {} + static VolumeCache* m_Instance; + + struct StaticInit + { + public: + StaticInit(); + }; + static StaticInit m_StaticInit; + + typedef std::map FileHandleMap; + FileHandleMap m_FileHandleMap; + + typedef std::map CacheInstanceMap; + CacheInstanceMap m_CacheInstanceMap; + + // load a grid from an OpenVDB file and create a new CacheInstance for it + Handle readOpenVDBGrid(const std::string& filename, const std::string& gridName, bool openToNanoVDB); + Handle readNanoVDBGrid(const std::string& filename, const std::string& gridName, bool openToOpenVDB); + + //Handle readField3DField(const std::string& filename, const std::string& fieldName); + //Handle readBiforstField(const std::string& filename, const std::string& channelName); + //Handle readAuraField(const std::string& filename, const std::string& channelName); + + uint32_t m_NumEntries; + + friend class VolumeCache::StaticInit; +}; + +/// OpenVDB CacheInstance implementation +class OpenVDBCacheInstance: public CacheInstance +{ +public: + OpenVDBCacheInstance(VolumeCache::Handle h, openvdb::GridBase::Ptr grid); + + template + auto sample(int interplotion, const Imath::V3d& wsP) const -> typename GridType::ValueType; + + template + void march_extents(const AtVolumeIntersectionInfo* info, const openvdb::math::Ray& ray, const Intersector* master_intersector); + + void bounds(Imath::V3d& bbmin, Imath::V3d& bbmax) const; + + size_t memUsage() const; + + Imath::V3d voxelSize() const; + + openvdb::GridBase::Ptr m_Grid; + VolumeCache::Handle m_Handle; + + typedef boost::shared_ptr Ptr; +}; + +class NanoVDBCacheInstance : public CacheInstance +{ +public: + NanoVDBCacheInstance(VolumeCache::Handle, nanovdb::GridHandle<> gridHandle); + + template + auto sample(int interplotion, const Imath::V3d& wsP) const -> typename GridType; + + bool march_extents(const AtVolumeIntersectionInfo* info, const Imath::V3f &ray_original, const Imath::V3f &ray_direction, float t0, float t1); + + void bounds(Imath::V3d& bbmin, Imath::V3d& bbmax) const; + size_t memUsage() const; + + Imath::V3d voxelSize() const; + + nanovdb::GridHandle<>* m_GridHandle; + VolumeCache::Handle m_Handle; + + typedef boost::shared_ptr Ptr; +}; diff --git a/src/apVolume/apVolume.cpp b/src/apVolume/apVolume.cpp new file mode 100644 index 0000000..d2f01a2 --- /dev/null +++ b/src/apVolume/apVolume.cpp @@ -0,0 +1,481 @@ +#include +#include + +#include +#include +#include +#include + +#include +#include + +AI_VOLUME_NODE_EXPORT_METHODS(apVolume) + +using FogVolumeRayIntersector = openvdb::tools::VolumeRayIntersector; +using Ray = openvdb::math::Ray; + +static const char* memory_category = "[apVolume] Plugin"; + +struct StringKeyHasher +{ + size_t operator ()(const std::string& key) const + { + return std::hash{}(key); + } + bool operator ()(const std::string& lhs, const std::string& rhs) const + { + return lhs == rhs; + } +}; + +template T max_comp(const openvdb::math::Vec3 v) +{ + return std::max(v.x(), std::max(v.y(), v.z())); +} + +enum class GridType : int +{ + Unknown, + Float, + Vec3s +}; + +struct Grid +{ + GridType type = GridType::Unknown; + int32_t offset = -1; +}; + +struct VolumeData +{ + VolumeData(){} + + ~VolumeData() + { + delete intersector; + } + + openvdb::GridBase::ConstPtr get_grid_ptr(const Grid& grid) const + { + assert(grid.offset >= 0); + switch (grid.type) + { + case GridType::Float: + assert(grid.offset < float_grids.size()); + return float_grids[grid.offset]; + case GridType::Vec3s: + assert(grid.offset < vec3s_grids.size()); + return vec3s_grids[grid.offset]; + default: + return openvdb::GridBase::ConstPtr(); + } + } + + std::unordered_map grids; + + std::vector float_grids; + std::vector vec3s_grids; + + openvdb::FloatGrid::ConstPtr density_grid; + openvdb::Vec3SGrid::Ptr converted_velocity_grid; + openvdb::Vec3SGrid::ConstPtr velocity_grid; + + float velocity_scale = 0; + float velocity_shutter_start = 0; + float velocity_shutter_end = 0; + + FogVolumeRayIntersector* intersector = nullptr; + + openvdb::math::CoordBBox total_bbox; + + std::string filename; +}; + +node_parameters +{ + AiParameterStr("filename", ""); + AiParameterArray("filedata", AiArrayAllocate(0, 0, AI_TYPE_BYTE)); + AiParameterFlt("step_scale", 1); + AiParameterBool("compress", true); + AiParameterArray("grids", AiArrayAllocate(0, 0, AI_TYPE_STRING)); + AiParameterArray("velocity_grids", AiArrayAllocate(0, 0, AI_TYPE_STRING)); + + AiParameterFlt("velocity_scale", 1); + AiParameterFlt("velocity_fps", 24); + AiParameterFlt("velocity_outlier_threshold", 0.001); +} + +template void upload_velocity_channel(openvdb::FloatGrid::ConstPtr comp_grid, openvdb::Vec3SGrid::Ptr velocity_grid) +{ + auto op = [](const openvdb::FloatGrid::ValueOnCIter& it, openvdb::Vec3SGrid::Accessor& accessor) + { + if (it.isVoxelValue()) // set a single voxel + { + const float value = it.getValue(); + accessor.modifyValue(it.getCoord(), [value](openvdb::Vec3s& val) + { + switch (comp) + { + case 0: + val.x() = value; + break; + case 1: + val.y() = value; + break; + case 2: + val.z() = value; + break; + } + }); + } + }; + + openvdb::tools::transformValues(comp_grid->cbeginValueOn(), *velocity_grid, op, false); +} + +volume_create +{ + auto volume_data = std::make_unique(); + + std::string filename = AiNodeGetStr(node, "filename").c_str(); + std::string ext = filename.substr(filename.find_last_of(".") + 1); + volume_data->filename = filename; + AiMsgInfo("[apVolume] : Opened file : '%s'", filename.c_str()); + + std::string density_grid_name = "density"; + + if (ext == "vdb") + { + AiMsgInfo("[apVolume] : OpenVDB version %s", OPENVDB_LIBRARY_VERSION_STRING); + openvdb::initialize(); + openvdb::io::File file(filename); + file.open(false); + + if (file.getGrids()->empty()) + { + AiMsgInfo("[apVolume] : File not contain any grid : '%s'", filename.c_str()); + return false; + } + + auto grid_reader = [&](const std::string grid_name) -> bool + { + auto grid = file.readGrid(grid_name); + AiMsgInfo("[apVolume] : Read Grid: %s, Type: %s", grid_name.c_str(), grid->type().c_str()); + const std::string name(grid_name.c_str()); + if (grid->isType()) + { + volume_data->grids[name].type = GridType::Float; + volume_data->grids[name].offset = volume_data->float_grids.size(); + volume_data->float_grids.push_back(openvdb::gridConstPtrCast(grid)); + + if ((!volume_data->density_grid) || grid_name == density_grid_name) + { + volume_data->density_grid = openvdb::gridConstPtrCast(grid); + AiMsgInfo("[apVolume] : Init volume_data->density_grid"); + } + } + else if (grid->isType()) + { + volume_data->grids[name].type = GridType::Vec3s; + volume_data->grids[name].offset = volume_data->vec3s_grids.size(); + volume_data->vec3s_grids.push_back(openvdb::gridConstPtrCast(grid)); + } + else + { + AiMsgWarning("[apVolume] : Unknown type '%s' of grid '%s'. Ignoring", grid->type().c_str(), grid_name.c_str()); + return false; + } + return true; + }; + AtArray *grids = AiNodeGetArray(node, "grids"); + + if (AiArrayGetNumElements(grids)) + { + for (int i = 0; i < AiArrayGetNumElements(grids); i++) + { + std::string grid_name = AiArrayGetStr(grids, i); + if (!file.hasGrid(grid_name)) + { + AiMsgWarning("[apVolume] : '%s' doesn't have grid with name '%s'", filename , grid_name.c_str()); + continue; + } + grid_reader(grid_name); + } + } + else + { + for (auto name_it = file.beginName(); name_it != file.endName(); ++name_it) + { + grid_reader(name_it.gridName()); + } + } + + if (!volume_data->density_grid) + { + AiMsgError("[apVolume] : There is no grid with type Float. Plugin can raytrace only through the volume of type float"); + return false; + } + + AtArray *velocity_grids = AiNodeGetArray(node, "velocity_grids"); + for (int i = 0; i < AiArrayGetNumElements(velocity_grids); i++) + { + std::string grid_name = AiArrayGetStr(velocity_grids, i); + auto find_it = volume_data->grids.find(grid_name); + if (file.hasGrid(grid_name) || find_it != volume_data->grids.end()) + { + openvdb::GridBase::ConstPtr grid; + if (find_it == volume_data->grids.end()) + { + grid = file.readGrid(grid_name); + } + else + { + grid = volume_data->get_grid_ptr(find_it->second); + } + + if (openvdb::Vec3SGrid::gridType() == grid->type()) + { + volume_data->velocity_grid = openvdb::gridConstPtrCast(grid); + AiAddMemUsage(grid->memUsage(), AtString(memory_category)); + } + else if (openvdb::FloatGrid::gridType() == grid->type()) + { + auto comp_grid = openvdb::gridConstPtrCast(grid); + + if (!volume_data->velocity_grid) + { + volume_data->converted_velocity_grid = openvdb::Vec3SGrid::create(openvdb::zeroVal()); + volume_data->converted_velocity_grid->setTransform(volume_data->density_grid->transform().copy()); + volume_data->velocity_grid = openvdb::gridConstPtrCast(volume_data->converted_velocity_grid); + AiAddMemUsage(volume_data->converted_velocity_grid->memUsage(), AtString(memory_category)); + } + else if (!volume_data->converted_velocity_grid) + { + AiMsgError("[apVolume] : we've already initialized with velocity grids. Invalid specifications on velocity_grids?"); + break; + } + + if (grid_name.back() == 'X' || grid_name.back() == 'x') + { + AiMsgDebug("[apVolume] : reading X channel for velocity grid from '%s'", grid_name.c_str()); + upload_velocity_channel<0>(comp_grid, volume_data->converted_velocity_grid); + } + else if (grid_name.back() == 'Y' || grid_name.back() == 'y') + { + AiMsgDebug("[apVolume] : reading Y channel for velocity grid from '%s'", grid_name.c_str()); + upload_velocity_channel<1>(comp_grid, volume_data->converted_velocity_grid); + } + else // Z component + { + AiMsgDebug("[apVolume] : reading Z channel for velocity grid from '%s'", grid_name.c_str()); + upload_velocity_channel<2>(comp_grid, volume_data->converted_velocity_grid); + } + } + } + + + } + + openvdb::Vec3s min_velocity(0, 0, 0); + openvdb::Vec3s max_velocity(0, 0, 0); + + if (volume_data->velocity_grid) + { + volume_data->velocity_grid->evalMinMax(min_velocity, max_velocity); + + volume_data->velocity_scale = AiNodeGetFlt(node, "velocity_scale"); + volume_data->velocity_shutter_start = AiNodeGetFlt(node, "motion_start"); + volume_data->velocity_shutter_end = AiNodeGetFlt(node, "motion_end"); + } + + openvdb::BBoxd total_bbox; + + for (auto& grid_it : volume_data->grids) + { + openvdb::GridBase::ConstPtr grid = volume_data->get_grid_ptr(grid_it.second); + + if (!grid) + continue; + + auto grid_bbox = grid->evalActiveVoxelBoundingBox(); + auto world_grid_bbox = grid->transform().indexToWorld(grid_bbox); + + if (volume_data->velocity_grid && volume_data->velocity_scale > 0) + { + world_grid_bbox.expand(max_velocity * volume_data->velocity_scale); + + grid_bbox = grid->transform().worldToIndexNodeCentered(world_grid_bbox); + } + + volume_data->total_bbox.expand(grid_bbox); + total_bbox.expand(world_grid_bbox); + } + volume_data->total_bbox.max().offset(1); + + switch (volume_data->density_grid->getGridClass()) + { + case openvdb::GRID_LEVEL_SET: + AiMsgError("[apVolume] : Ray-marching through the level set is not supported!"); + return false; + break; + default: + volume_data->intersector = new FogVolumeRayIntersector(*volume_data->density_grid, volume_data->total_bbox); + break; + } + + data->auto_step_size = max_comp(volume_data->density_grid->voxelSize()); + + data->bbox.min.x = total_bbox.min().x(); + data->bbox.min.y = total_bbox.min().y(); + data->bbox.min.z = total_bbox.min().z(); + data->bbox.max.x = total_bbox.max().x(); + data->bbox.max.y = total_bbox.max().y(); + data->bbox.max.z = total_bbox.max().z(); + + data->private_info = volume_data.release(); + } + + return true; +} + +volume_update +{ + auto volume_data = static_cast(data->private_info); + return true; +} + +volume_gradient +{ + return false; +} + +template +auto sample_grid(int interpolation, const typename GridType::ConstUnsafeAccessor& accessor, + const openvdb::math::Transform& transform, const openvdb::Vec3d sampling_point) -> typename GridType::ValueType +{ + using namespace openvdb::tools; + using Result = GridType::ValueType; + + const auto index_point = transform.worldToIndex(sampling_point); + Result result = openvdb::zeroVal(); + + switch (interpolation) + { + case AI_VOLUME_INTERP_CLOSEST: + PointSampler::sample(accessor, index_point, result); + break; + case AI_VOLUME_INTERP_TRILINEAR: + BoxSampler::sample(accessor, index_point, result); + break; + case AI_VOLUME_INTERP_TRICUBIC: + QuadraticSampler::sample(accessor, index_point, result); + break; + } + + return result; +} + +volume_sample +{ + auto volume_data = static_cast(data->private_info); + + if (!volume_data) + return false; + + auto grid_it = volume_data->grids.find(channel.c_str()); + if (grid_it == volume_data->grids.end()) + { + return false; + } + + const auto& grid = grid_it->second; + openvdb::Vec3d sampling_point(sg->Po.x, sg->Po.y, sg->Po.z); + + const float shutter_start = AiCameraGetShutterStart(); + const float shutter_end = AiCameraGetShutterEnd(); + + if (shutter_start != shutter_end && volume_data->velocity_grid) + { + auto accessor = volume_data->velocity_grid->getConstUnsafeAccessor(); + + auto velocity = accessor.getValue(volume_data->velocity_grid->transform().worldToIndexCellCentered(sampling_point)); + + const float rel_time = (sg->time - shutter_start) / (shutter_end - shutter_start); + const float vel_time = AiLerp(rel_time, volume_data->velocity_shutter_start, volume_data->velocity_shutter_end); + + sampling_point = sampling_point - velocity * vel_time * volume_data->velocity_scale; + } + + switch (grid.type) + { + case GridType::Float: + { + const auto& grid_ptr = volume_data->float_grids[grid.offset]; + auto accessor = grid_ptr->getConstUnsafeAccessor(); + + value->FLT() = sample_grid(interp, accessor, grid_ptr->transform(), sampling_point); + *type = AI_TYPE_FLOAT; + } + break; + case GridType::Vec3s: + { + const auto& grid_ptr = volume_data->vec3s_grids[grid.offset]; + auto accessor = grid_ptr->getConstUnsafeAccessor(); + const auto temp = sample_grid(interp, accessor, grid_ptr->transform(), sampling_point); + + value->VEC() = AtVector(temp.x(), temp.y(), temp.z()); + *type = AI_TYPE_VECTOR; + } + break; + } + + return true; +} + +template void march_extents(const AtVolumeIntersectionInfo* info, const Ray& ray, const Intersector* master_intersector) +{ + Intersector intersector(*master_intersector); + + if (intersector.setWorldRay(ray)) + { + Intersector::RealType t_min, t_max; + while (intersector.march(t_min, t_max)) + { + const auto near_pos = intersector.getWorldPos(t_min); + const auto far_pos = intersector.getWorldPos(t_max); + + t_min = (near_pos - ray.eye()).length(); + t_max = (far_pos - ray.eye()).length(); + + AiVolumeAddIntersection(info, t_min, t_max); + } + } +} + +volume_ray_extents +{ + auto volume_data = static_cast(data->private_info); + if (volume_data && volume_data->intersector) + { + const openvdb::Vec3s ray_origin(origin->x, origin->y, origin->z); + const openvdb::Vec3s ray_direction(direction->x, direction->y, direction->z); + + Ray ray(ray_origin, ray_direction, t0, t1); + // AiMsgInfo("ray_origin : %f, %f, %f", ray_origin[0], ray_origin[1], ray_origin[2]); + // AiMsgInfo("ray_direction : %f, %f, %f", ray_direction[0], ray_direction[1], ray_direction[2]); + march_extents(info, ray, volume_data->intersector); + } +} + +volume_cleanup +{ + bool status = false; + auto volume_data = static_cast(data->private_info); + if (volume_data) + { + delete volume_data; + status = true; + } + openvdb::uninitialize(); + return status; +} \ No newline at end of file diff --git a/src/apVolume/apVolume.mtd b/src/apVolume/apVolume.mtd new file mode 100644 index 0000000..da120e0 --- /dev/null +++ b/src/apVolume/apVolume.mtd @@ -0,0 +1,4 @@ +[node apVolume] + maya.name STRING "apVolume" + maya.id INT 0x0005103 + maya.classification STRING "shader/volume" \ No newline at end of file diff --git a/src/apVolume/apVolumeShader.cpp b/src/apVolume/apVolumeShader.cpp new file mode 100644 index 0000000..7e2fe61 --- /dev/null +++ b/src/apVolume/apVolumeShader.cpp @@ -0,0 +1,222 @@ +#include +#include +//#include +//#include + +#include "VolumeCache.h" + +AI_SHADER_NODE_EXPORT_METHODS(apVolumeShader) + +#define NUM_BB_STEPS 10000 + +enum apVolumeParams +{ + p_filename, + p_step_scale, + p_compress, + p_velocity_scale, + p_velocity_fps, + p_velocity_outlier_threshold, + p_use_nanovdb, + p_density, + p_density_channel, + p_scatter, + p_scatter_color, + p_scatter_channel, + p_scatter_anisotropy, + p_transparency, + p_transparency_depth, + p_transparency_channel, + p_emission_mode, + p_emission, + p_emission_color, + p_emission_channel, + p_temperature, + p_temperature_channel, + p_blackbody_kelvin, + p_blackbody_intensity, + p_displacement, + p_interpolation +}; + +static const char* InterpolationNames[] = { + "closest", + "trilieanr", + "tricubic", + NULL +}; + +static const char* EmissionModeNames[] = { + "none", + "channel", + "density", + "blackbody", + NULL +}; + +struct ShaderData +{ + CacheInstance::Ptr densityCache; + CacheInstance::Ptr temperatureCache; + std::string filename; + + std::string density_channel; + std::string temperature_channel; + std::string emission_channel; + std::string transparency_channel; + + int emission_mode; + int interpolation; + + float velicoty_scale; + float velocity_fps; + float velocity_outlier_threshold; + bool use_nanovdb; +}; + +node_parameters +{ + AiParameterStr("filename", ""); + AiParameterFlt("step_scale", 1); + AiParameterBool("compress", true); + + AiParameterFlt("velocity_scale", 1); + AiParameterFlt("velocity_fps", 24); + AiParameterFlt("velocity_outlier_threshold", 0.001); + AiParameterBool("use_nanovdb", true); + + AiParameterFlt("density", 1.0); + AiParameterStr("density_channel", "density"); + AiParameterFlt("scatter", 1.0); + AiParameterRGB("scatter_color", 0.5, 0.5, 0.5); + AiParameterStr("scatter_color_channel", ""); + AiParameterFlt("scatter_anisotropy", 0); + AiParameterRGB("transparency", 0.367879, 0.367879, 0.367879); + AiParameterFlt("transparency_depth", 1); + AiParameterStr("transparency_channel", ""); + AiParameterEnum("emission_mode", 3, EmissionModeNames); + AiParameterFlt("emission", 1); + AiParameterRGB("emission_color", 1, 1, 1); + AiParameterStr("emission_channel", "heat"); + AiParameterFlt("temperature", 1); + AiParameterStr("temperature_channel", "temperature"); + AiParameterFlt("blackbody_kelvin", 5000); + AiParameterFlt("blackbody_intensity", 1.0); + AiParameterVec("displacement", 0, 0, 0); + AiParameterEnum("interpolation", 0, InterpolationNames); +} + +node_initialize +{ + AiNodeSetLocalData(node, new ShaderData); + ShaderData *data = (ShaderData*)AiNodeGetLocalData(node); + openvdb::initialize(); +} + +node_update +{ + ShaderData *data = (ShaderData*)AiNodeGetLocalData(node); + + data->filename = AiNodeGetStr(node, "filename").c_str(); + data->velicoty_scale = AiNodeGetFlt(node, "velicoty_scale"); + data->density_channel = AiNodeGetStr(node, "density_channel").c_str(); + data->transparency_channel = AiNodeGetStr(node, "transparency_channel").c_str(); + data->emission_channel = AiNodeGetStr(node, "emission_channel").c_str(); + data->temperature_channel = AiNodeGetStr(node, "temperature_channel").c_str(); + data->emission_mode = AiNodeGetInt(node, "emission_mode"); + data->interpolation = AiNodeGetInt(node, "interpolation"); + data->use_nanovdb = AiNodeGetBool(node, "use_nanovdb"); + if (data->density_channel != "") + { + VolumeCache::Handle handle = VolumeCache::instance()->readField(data->filename, data->density_channel, data->use_nanovdb); + if (handle < 0) + { + AiMsgError("## [apVolume] : Could not load field '%s' from file '%s'", data->density_channel, data->filename.c_str()); + } + else + { + data->densityCache = VolumeCache::instance()->getCacheInstance(handle); + } + } + + if (data->temperature_channel != "") + { + VolumeCache::Handle h = VolumeCache::instance()->readField(data->filename, data->temperature_channel, data->use_nanovdb); + if (h < 0) + { + AiMsgError("## [apVolume] : Could not load field '%s' from file '%s'", data->temperature_channel.c_str(), data->filename.c_str()); + } + else + { + data->temperatureCache = VolumeCache::instance()->getCacheInstance(h); + } + } + + /*std::string filename = AiNodeGetStr(node, "filename").c_str(); + AiMsgInfo("## node_update :: Open : %s", filename.c_str()); + std::string ext = filename.substr(filename.find_last_of(".") + 1); + if (ext == "vdb") + { + openvdb::io::File file(filename); + file.open(false); + auto grids = file.getGrids(); + for (auto& grid : *grids) + { + grid->getName(); + } + } + + if (ext == "nvdb") + { + auto grids = nanovdb::io::readGrids(filename); + } + + AtArray *grids = AiNodeGetArray(node, "grids"); + */ +} + +node_finish +{ + if (AiNodeGetLocalData(node)) + { + ShaderData* data = (ShaderData*)AiNodeGetLocalData(node); + delete data; + AiNodeSetLocalData(node, NULL); + } +} + +shader_evaluate +{ + ShaderData* data = (ShaderData*)AiNodeGetLocalData(node); + float density = AiShaderEvalParamFlt(p_density); + float scatter = AiShaderEvalParamFlt(p_scatter); + AtRGB scatter_color = AiShaderEvalParamRGB(p_scatter_color); + float emission = AiShaderEvalParamFlt(p_emission); + AtRGB emission_color = AiShaderEvalParamRGB(p_emission_color); + AtRGB absorption = AtRGB(0.5); + float g = AiShaderEvalParamFlt(p_scatter_anisotropy); + scatter_color *= scatter; + Imath::V3d wsP(sg->Po.x, sg->Po.y, sg->Po.z); + float d = 0.0f; + + if (data && data->densityCache) + { + d = *static_cast(data->densityCache->lookup(wsP)); + } + + d *= density; + scatter_color *= d; + + if (emission > 0) + { + float temperature = AiShaderEvalParamFlt(p_temperature); + float t = 0.0f; + if (data && data->temperatureCache) + { + t = *static_cast(data->temperatureCache->lookup(wsP)); + } + } + AtClosureList closures; + closures.add(AiClosureVolumeHenyeyGreenstein(sg, absorption, scatter_color, emission_color, g)); + sg->out.CLOSURE() = closures; +} diff --git a/src/apVolume/loader.cpp b/src/apVolume/loader.cpp new file mode 100644 index 0000000..0ea9141 --- /dev/null +++ b/src/apVolume/loader.cpp @@ -0,0 +1,32 @@ +#include + +extern const AtNodeMethods* apVolume; +extern const AtNodeMethods* apVolumeShader; +namespace { + enum { + AP_VOLUME, + AP_VOLUME_SHADER + }; +} + +node_loader +{ + strcpy(node->version, AI_VERSION); + switch (i) { + case AP_VOLUME: + node->methods = apVolume; + node->output_type = AI_TYPE_NONE; + node->name = "apVolume"; + node->node_type = AI_NODE_SHAPE_VOLUME; + break; + /*case AP_VOLUME_SHADER: + node->methods = apVolumeShader; + node->output_type = AI_TYPE_CLOSURE; + node->name = "apVolumeShader"; + node->node_type = AI_NODE_SHADER; + break;*/ + default: + return false; + } + return true; +} \ No newline at end of file diff --git a/src/apZinkeBSDF/apZinkeBSDF.cpp b/src/apZinkeBSDF/apZinkeBSDF.cpp new file mode 100644 index 0000000..58c7f04 --- /dev/null +++ b/src/apZinkeBSDF/apZinkeBSDF.cpp @@ -0,0 +1,62 @@ +#include "ai.h" + +AI_SHADER_NODE_EXPORT_METHODS(apZinkeBSDF) + +enum apHairBSDFParams +{ + p_weight, + p_opacity +}; + + +struct ShaderData +{ +}; + +node_parameters +{ + AiParameterRGB("weight", 0.0, 0.0, 0.0); + AiParameterRGB("opacity", 1, 1, 1); +} + +node_initialize +{ + ShaderData *data = (ShaderData *)AiMalloc(sizeof(ShaderData)); + AiNodeSetLocalData(node, data); +} + +node_update +{ +} + +node_finish +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AiFree(data); +} + +shader_evaluate +{ + ShaderData *data = (ShaderData *)AiNodeGetLocalData(node); + AtRGB weight = AiShaderEvalParamRGB(p_weight); + AtRGB opacity = AiShaderEvalParamRGB(p_opacity); + AtBSDF *bsdf = AiZinkeBSDF(sg, weight, sg->dPdv); + + AtClosureList closures; + closures.add(bsdf); + closures.add(AiClosureTransparent(sg, 1.0 - opacity)); + sg->out.CLOSURE() = closures; +} + +node_loader +{ + if (i > 0) + return false; + + node->methods = apZinkeBSDF; + node->output_type = AI_TYPE_CLOSURE; + node->name = "apZinkeBSDF"; + node->node_type = AI_NODE_SHADER; + strcpy(node->version, AI_VERSION); + return true; +} diff --git a/src/apZinkeBSDF/apZinkeBSDF.mtd b/src/apZinkeBSDF/apZinkeBSDF.mtd new file mode 100644 index 0000000..dcd9576 --- /dev/null +++ b/src/apZinkeBSDF/apZinkeBSDF.mtd @@ -0,0 +1,14 @@ +[node apZinkeBSDF] + maya.name STRING "apZinkeBSDF" + maya.id INT 0x0005113 + maya.classification STRING "shader/surface" + +[attr weight] + desc STRING "Weight" + maya.keyable BOOL false + linkable BOOL true + +[attr opacity] + desc STRING "Opacity" + maya.keyable BOOL false + linkable BOOL true diff --git a/src/apZinkeBSDF/apZinkeBSDFTemplate.py b/src/apZinkeBSDF/apZinkeBSDFTemplate.py new file mode 100644 index 0000000..7c552f2 --- /dev/null +++ b/src/apZinkeBSDF/apZinkeBSDFTemplate.py @@ -0,0 +1,14 @@ +import pymel.core as pm +from mtoa.ui.ae.shaderTemplate import ShaderAETemplate + +class AEapZinkeBSDFTemplate(ShaderAETemplate): + def setup(self): + self.addSwatch() + self.beginLayout("BSDF Attribues", collapse=False) + self.addControl('weight', label='Weight', annotation='Weight') + self.addControl('opacity', label='Opacity') + self.endLayout() + pm.mel.AEdependNodeTemplate(self.nodeName) + self.addExtraControls() + self.endScrollLayout() + \ No newline at end of file diff --git a/tests/.mayaSwatches/volume.ma.swatches b/tests/.mayaSwatches/volume.ma.swatches new file mode 100644 index 0000000..b818e4c Binary files /dev/null and b/tests/.mayaSwatches/volume.ma.swatches differ diff --git a/tests/texture_random.ass b/tests/texture_random.ass new file mode 100644 index 0000000..2415c38 --- /dev/null +++ b/tests/texture_random.ass @@ -0,0 +1,330 @@ +### exported: Fri Oct 28 09:35:19 2022 +### from: Arnold 6.2.1.1 [fbf3b21a] windows clang-10.0.1 oiio-2.3.2 osl-1.12.0 vdb-7.1.1 clm-2.0.0.235 rlm-14.1.3 optix-6.6.0 2021/06/04 18:35:03 +### host app: MtoA 4.2.4 3c94e997 (fix-4.2.4) Maya 2020 +### user: indigo +### render_layer: defaultRenderLayer +### scene: C:/Users/indigo/Documents/maya/projects/default/scenes/testTextureRandom.ma + + + +options +{ + AA_samples 3 + outputs "RGBA RGBA defaultArnoldFilter/gaussian_filter defaultArnoldDriver/driver_exr.RGBA" + xres 960 + yres 540 + texture_per_file_stats on + texture_searchpath "C:/Users/indigo/Documents/maya/projects/default/sourceimages" + texture_automip off + camera "/persp/perspShape" + color_manager "defaultColorMgtGlobals" + frame 1 + procedural_searchpath "C:/Users/indigo/Documents/maya/projects/default/" + GI_diffuse_depth 1 + GI_specular_depth 1 + GI_transmission_depth 8 + declare render_layer constant STRING + render_layer "defaultRenderLayer" +} + +gaussian_filter +{ + name defaultArnoldFilter/gaussian_filter +} + +driver_exr +{ + name defaultArnoldDriver/driver_exr.RGBA + filename "C:/Users/indigo/Documents/maya/projects/default/images/testTextureRandom.exr" + color_space "" +} + +color_manager_syncolor +{ + name defaultColorMgtGlobals + native_catalog_path "C:/Program Files/Autodesk/Maya2020/synColor" + custom_catalog_path "C:/Users/indigo/Documents/maya/synColor/Shared/" + rendering_color_space "scene-linear Rec 709/sRGB" +} + +polymesh +{ + name /pPlane1/pPlaneShape1 + visibility 255 + sidedness 255 + matrix + 26.9280205 0 0 0 + 0 26.9280205 0 0 + 0 0 26.9280205 0 + 0 0 0 1 + shader "surfaceShader1" + id 3518428338 + nsides 100 1 UINT + 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 + 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 + 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 + vidxs 400 1 UINT + 0 1 12 11 1 2 13 12 2 3 14 13 3 4 15 14 4 5 16 15 5 6 17 16 6 7 18 17 7 8 19 18 8 + 9 20 19 9 10 21 20 11 12 23 22 12 13 24 23 13 14 25 24 14 15 26 25 15 16 27 26 16 + 17 28 27 17 18 29 28 18 19 30 29 19 20 31 30 20 21 32 31 22 23 34 33 23 24 35 34 + 24 25 36 35 25 26 37 36 26 27 38 37 27 28 39 38 28 29 40 39 29 30 41 40 30 31 42 + 41 31 32 43 42 33 34 45 44 34 35 46 45 35 36 47 46 36 37 48 47 37 38 49 48 38 39 + 50 49 39 40 51 50 40 41 52 51 41 42 53 52 42 43 54 53 44 45 56 55 45 46 57 56 46 + 47 58 57 47 48 59 58 48 49 60 59 49 50 61 60 50 51 62 61 51 52 63 62 52 53 64 63 + 53 54 65 64 55 56 67 66 56 57 68 67 57 58 69 68 58 59 70 69 59 60 71 70 60 61 72 + 71 61 62 73 72 62 63 74 73 63 64 75 74 64 65 76 75 66 67 78 77 67 68 79 78 68 69 + 80 79 69 70 81 80 70 71 82 81 71 72 83 82 72 73 84 83 73 74 85 84 74 75 86 85 75 + 76 87 86 77 78 89 88 78 79 90 89 79 80 91 90 80 81 92 91 81 82 93 92 82 83 94 93 + 83 84 95 94 84 85 96 95 85 86 97 96 86 87 98 97 88 89 100 99 89 90 101 100 90 91 + 102 101 91 92 103 102 92 93 104 103 93 94 105 104 94 95 106 105 95 96 107 106 96 + 97 108 107 97 98 109 108 99 100 111 110 100 101 112 111 101 102 113 112 102 103 114 + 113 103 104 115 114 104 105 116 115 105 106 117 116 106 107 118 117 107 108 119 118 + 108 109 120 119 + nidxs 400 1 UINT + 0 1 2 3 1 4 5 2 4 6 7 5 6 8 9 7 8 10 11 9 10 12 13 11 12 14 15 13 14 16 17 15 16 + 18 19 17 18 20 21 19 3 2 22 23 2 5 24 22 5 7 25 24 7 9 26 25 9 11 27 26 11 13 28 + 27 13 15 29 28 15 17 30 29 17 19 31 30 19 21 32 31 23 22 33 34 22 24 35 33 24 25 + 36 35 25 26 37 36 26 27 38 37 27 28 39 38 28 29 40 39 29 30 41 40 30 31 42 41 31 + 32 43 42 34 33 44 45 33 35 46 44 35 36 47 46 36 37 48 47 37 38 49 48 38 39 50 49 + 39 40 51 50 40 41 52 51 41 42 53 52 42 43 54 53 45 44 55 56 44 46 57 55 46 47 58 + 57 47 48 59 58 48 49 60 59 49 50 61 60 50 51 62 61 51 52 63 62 52 53 64 63 53 54 + 65 64 56 55 66 67 55 57 68 66 57 58 69 68 58 59 70 69 59 60 71 70 60 61 72 71 61 + 62 73 72 62 63 74 73 63 64 75 74 64 65 76 75 67 66 77 78 66 68 79 77 68 69 80 79 + 69 70 81 80 70 71 82 81 71 72 83 82 72 73 84 83 73 74 85 84 74 75 86 85 75 76 87 + 86 78 77 88 89 77 79 90 88 79 80 91 90 80 81 92 91 81 82 93 92 82 83 94 93 83 84 + 95 94 84 85 96 95 85 86 97 96 86 87 98 97 89 88 99 100 88 90 101 99 90 91 102 101 + 91 92 103 102 92 93 104 103 93 94 105 104 94 95 106 105 95 96 107 106 96 97 108 107 + 97 98 109 108 100 99 110 111 99 101 112 110 101 102 113 112 102 103 114 113 103 104 + 115 114 104 105 116 115 105 106 117 116 106 107 118 117 107 108 119 118 108 109 120 + 119 + uvidxs 400 1 UINT + 0 1 12 11 1 2 13 12 2 3 14 13 3 4 15 14 4 5 16 15 5 6 17 16 6 7 18 17 7 8 19 18 8 + 9 20 19 9 10 21 20 11 12 23 22 12 13 24 23 13 14 25 24 14 15 26 25 15 16 27 26 16 + 17 28 27 17 18 29 28 18 19 30 29 19 20 31 30 20 21 32 31 22 23 34 33 23 24 35 34 + 24 25 36 35 25 26 37 36 26 27 38 37 27 28 39 38 28 29 40 39 29 30 41 40 30 31 42 + 41 31 32 43 42 33 34 45 44 34 35 46 45 35 36 47 46 36 37 48 47 37 38 49 48 38 39 + 50 49 39 40 51 50 40 41 52 51 41 42 53 52 42 43 54 53 44 45 56 55 45 46 57 56 46 + 47 58 57 47 48 59 58 48 49 60 59 49 50 61 60 50 51 62 61 51 52 63 62 52 53 64 63 + 53 54 65 64 55 56 67 66 56 57 68 67 57 58 69 68 58 59 70 69 59 60 71 70 60 61 72 + 71 61 62 73 72 62 63 74 73 63 64 75 74 64 65 76 75 66 67 78 77 67 68 79 78 68 69 + 80 79 69 70 81 80 70 71 82 81 71 72 83 82 72 73 84 83 73 74 85 84 74 75 86 85 75 + 76 87 86 77 78 89 88 78 79 90 89 79 80 91 90 80 81 92 91 81 82 93 92 82 83 94 93 + 83 84 95 94 84 85 96 95 85 86 97 96 86 87 98 97 88 89 100 99 89 90 101 100 90 91 + 102 101 91 92 103 102 92 93 104 103 93 94 105 104 94 95 106 105 95 96 107 106 96 + 97 108 107 97 98 109 108 99 100 111 110 100 101 112 111 101 102 113 112 102 103 114 + 113 103 104 115 114 104 105 116 115 105 106 117 116 106 107 118 117 107 108 119 118 + 108 109 120 119 + vlist 121 1 VECTOR + -0.5 0 0.5 -0.400000006 0 0.5 -0.300000012 0 0.5 -0.199999988 0 0.5 -0.099999994 0 0.5 + 0 0 0.5 0.100000024 0 0.5 0.199999988 0 0.5 0.300000012 0 0.5 0.400000036 0 0.5 0.5 0 0.5 + -0.5 0 0.400000006 -0.400000006 0 0.400000006 -0.300000012 0 0.400000006 -0.199999988 0 0.400000006 + -0.099999994 0 0.400000006 0 0 0.400000006 0.100000024 0 0.400000006 0.199999988 0 0.400000006 + 0.300000012 0 0.400000006 0.400000036 0 0.400000006 0.5 0 0.400000006 -0.5 0 0.300000012 + -0.400000006 0 0.300000012 -0.300000012 0 0.300000012 -0.199999988 0 0.300000012 + -0.099999994 0 0.300000012 0 0 0.300000012 0.100000024 0 0.300000012 0.199999988 0 0.300000012 + 0.300000012 0 0.300000012 0.400000036 0 0.300000012 0.5 0 0.300000012 -0.5 0 0.199999988 + -0.400000006 0 0.199999988 -0.300000012 0 0.199999988 -0.199999988 0 0.199999988 + -0.099999994 0 0.199999988 0 0 0.199999988 0.100000024 0 0.199999988 0.199999988 0 0.199999988 + 0.300000012 0 0.199999988 0.400000036 0 0.199999988 0.5 0 0.199999988 -0.5 0 0.099999994 + -0.400000006 0 0.099999994 -0.300000012 0 0.099999994 -0.199999988 0 0.099999994 + -0.099999994 0 0.099999994 0 0 0.099999994 0.100000024 0 0.099999994 0.199999988 0 0.099999994 + 0.300000012 0 0.099999994 0.400000036 0 0.099999994 0.5 0 0.099999994 -0.5 0 0 -0.400000006 0 0 + -0.300000012 0 0 -0.199999988 0 0 -0.099999994 0 0 0 0 0 0.100000024 0 0 0.199999988 0 0 + 0.300000012 0 0 0.400000036 0 0 0.5 0 0 -0.5 0 -0.100000024 -0.400000006 0 -0.100000024 + -0.300000012 0 -0.100000024 -0.199999988 0 -0.100000024 -0.099999994 0 -0.100000024 + 0 0 -0.100000024 0.100000024 0 -0.100000024 0.199999988 0 -0.100000024 0.300000012 0 -0.100000024 + 0.400000036 0 -0.100000024 0.5 0 -0.100000024 -0.5 0 -0.199999988 -0.400000006 0 -0.199999988 + -0.300000012 0 -0.199999988 -0.199999988 0 -0.199999988 -0.099999994 0 -0.199999988 + 0 0 -0.199999988 0.100000024 0 -0.199999988 0.199999988 0 -0.199999988 0.300000012 0 -0.199999988 + 0.400000036 0 -0.199999988 0.5 0 -0.199999988 -0.5 0 -0.300000012 -0.400000006 0 -0.300000012 + -0.300000012 0 -0.300000012 -0.199999988 0 -0.300000012 -0.099999994 0 -0.300000012 + 0 0 -0.300000012 0.100000024 0 -0.300000012 0.199999988 0 -0.300000012 0.300000012 0 -0.300000012 + 0.400000036 0 -0.300000012 0.5 0 -0.300000012 -0.5 0 -0.400000036 -0.400000006 0 -0.400000036 + -0.300000012 0 -0.400000036 -0.199999988 0 -0.400000036 -0.099999994 0 -0.400000036 + 0 0 -0.400000036 0.100000024 0 -0.400000036 0.199999988 0 -0.400000036 0.300000012 0 -0.400000036 + 0.400000036 0 -0.400000036 0.5 0 -0.400000036 -0.5 0 -0.5 -0.400000006 0 -0.5 -0.300000012 0 -0.5 + -0.199999988 0 -0.5 -0.099999994 0 -0.5 0 0 -0.5 0.100000024 0 -0.5 0.199999988 0 -0.5 + 0.300000012 0 -0.5 0.400000036 0 -0.5 0.5 0 -0.5 + nlist 121 1 VECTOR + 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 + 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 + 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 + 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 + 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 + 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 + 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 + 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 + 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 + uvlist 121 1 VECTOR2 + 0.0122396946 0.0133402646 0.109382182 0.0133402646 0.206523985 0.0133402646 0.303666025 0.0133402646 + 0.400808275 0.0133402646 0.497950554 0.0133402646 0.595092356 0.0133402646 0.692234874 0.0133402646 + 0.789376855 0.0133402646 0.886519134 0.0133402646 0.983661413 0.0133402646 0.0122396946 0.110482514 + 0.109382182 0.110482514 0.206523985 0.110482514 0.303666025 0.110482514 0.400808275 0.110482514 + 0.497950554 0.110482514 0.595092356 0.110482514 0.692234874 0.110482514 0.789376855 0.110482514 + 0.886519134 0.110482514 0.983661413 0.110482514 0.0122396946 0.207624555 0.109382182 0.207624555 + 0.206523985 0.207624555 0.303666025 0.207624555 0.400808275 0.207624555 0.497950554 0.207624555 + 0.595092356 0.207624555 0.692234874 0.207624555 0.789376855 0.207624555 0.886519134 0.207624555 + 0.983661413 0.207624555 0.0122396946 0.304766804 0.109382182 0.304766804 0.206523985 0.304766804 + 0.303666025 0.304766804 0.400808275 0.304766804 0.497950554 0.304766804 0.595092356 0.304766804 + 0.692234874 0.304766804 0.789376855 0.304766804 0.886519134 0.304766804 0.983661413 0.304766804 + 0.0122396946 0.401908845 0.109382182 0.401908845 0.206523985 0.401908845 0.303666025 0.401908845 + 0.400808275 0.401908845 0.497950554 0.401908845 0.595092356 0.401908845 0.692234874 0.401908845 + 0.789376855 0.401908845 0.886519134 0.401908845 0.983661413 0.401908845 0.0122396946 0.499051094 + 0.109382182 0.499051094 0.206523985 0.499051094 0.303666025 0.499051094 0.400808275 0.499051094 + 0.497950554 0.499051094 0.595092356 0.499051094 0.692234874 0.499051094 0.789376855 0.499051094 + 0.886519134 0.499051094 0.983661413 0.499051094 0.0122396946 0.596193373 0.109382182 0.596193373 + 0.206523985 0.596193373 0.303666025 0.596193373 0.400808275 0.596193373 0.497950554 0.596193373 + 0.595092356 0.596193373 0.692234874 0.596193373 0.789376855 0.596193373 0.886519134 0.596193373 + 0.983661413 0.596193373 0.0122396946 0.693335414 0.109382182 0.693335414 0.206523985 0.693335414 + 0.303666025 0.693335414 0.400808275 0.693335414 0.497950554 0.693335414 0.595092356 0.693335414 + 0.692234874 0.693335414 0.789376855 0.693335414 0.886519134 0.693335414 0.983661413 0.693335414 + 0.0122396946 0.790477395 0.109382182 0.790477395 0.206523985 0.790477395 0.303666025 0.790477395 + 0.400808275 0.790477395 0.497950554 0.790477395 0.595092356 0.790477395 0.692234874 0.790477395 + 0.789376855 0.790477395 0.886519134 0.790477395 0.983661413 0.790477395 0.0122396946 0.887619674 + 0.109382182 0.887619674 0.206523985 0.887619674 0.303666025 0.887619674 0.400808275 0.887619674 + 0.497950554 0.887619674 0.595092356 0.887619674 0.692234874 0.887619674 0.789376855 0.887619674 + 0.886519134 0.887619674 0.983661413 0.887619674 0.0122396946 0.984761953 0.109382182 0.984761953 + 0.206523985 0.984761953 0.303666025 0.984761953 0.400808275 0.984761953 0.497950554 0.984761953 + 0.595092356 0.984761953 0.692234874 0.984761953 0.789376855 0.984761953 0.886519134 0.984761953 + 0.983661413 0.984761953 + smoothing on + disp_padding 0 + disp_height 1 + disp_zero_value 0 + disp_autobump off + autobump_visibility 1 + step_size 0 + volume_padding 0 + declare dcc_name constant STRING + dcc_name "pPlaneShape1" +} + +standard_surface +{ + name surfaceShader1 + base 0 + specular 0 + emission 1 + emission_color apTextureRandom1 + opacity 1 1 1 +} + +apTextureRandom +{ + name apTextureRandom1 + color3 ramp1 + scale 0.100000001 + probability 1 1 0 + pos_random 0.00999999978 1 + scale_max 2 2 + pixel_scale 1 + rotate_max 360 + overlap 30 +} + +ramp_rgb +{ + name ramp1 + type "custom" + input ramp1/uv.r + position 2 1 FLOAT +0.575875461 0.328793764 + interpolation 2 1 INT +1 1 + uvset "" + use_implicit_uvs "curves_only" + wrap_uvs on +} + +uv_transform +{ + name ramp1/uv + passthrough ramp1/uv_wave + uvset "" + rotate_frame 0 + wrap_frame_color 0.5 0.5 0.5 0 + repeat 10 10 + offset ramp1/noise + rotate 0 +} + +noise +{ + name ramp1/noise + amplitude 0.481707305 + scale 10.5365858 10.5365858 10.5365858 + offset 0.75 0.75 0.75 + coord_space "uv" + mode "scalar" +} + +uv_transform +{ + name ramp1/uv_wave + passthrough ramp1/ramp_float + offset ramp1/wave_mult +} + +multiply +{ + name ramp1/wave_mult + input1 -0.073170729 0.158536583 0 + input2 ramp1/trigo +} + +state_float +{ + name ramp1/state_v + variable "v" +} + +state_float +{ + name ramp1/state_u + variable "u" +} + +trigo +{ + name ramp1/trigo + input 0 0 0 + input.r ramp1/state_v + input.g ramp1/state_u + function "sin" + frequency 6.28318548 +} + +ramp_float +{ + name ramp1/ramp_float + type "circular" + interpolation 2 1 INT +1 1 + uvset "" + use_implicit_uvs "curves_only" +} + +persp_camera +{ + name /persp/perspShape + matrix + -0.364876777 5.55111512e-17 -0.931055844 0 + -0.675792873 0.687868893 0.264840335 0 + 0.640444338 0.725834966 -0.250987381 0 + 32.0689049 32.1577187 -13.938035 1 + near_clip 0.100000001 + far_clip 10000 + shutter_start 0 + shutter_end 0 + shutter_type "box" + rolling_shutter "off" + rolling_shutter_duration 0 + motion_start 0 + motion_end 0 + exposure 0 + fov 54.4322243 + uv_remap 0 0 0 1 + declare dcc_name constant STRING + dcc_name "perspShape" +} + diff --git a/tests/texture_random.bat b/tests/texture_random.bat new file mode 100644 index 0000000..ddbf4ec --- /dev/null +++ b/tests/texture_random.bat @@ -0,0 +1,10 @@ +@echo off + +set MAYA_VER=2020 +set MTOA_VER=4.2.4 +set ARNOLD_SDK_VER=6.2.1.1 +set APSHADER_ROOT=C:\workspace\apShaders\install\%MAYA_VER%\%ARNOLD_SDK_VER%\apShaders +set ARNOLD_PLUGIN_PATH=%ARNOLD_PLUGIN_PATH%;%APSHADER_ROOT%\shaders +set MTOA_LOCATION=C:\Autodesk\mtoa\%MTOA_VER%\%MAYA_VER% +set solidangle_LICENSE=5053@Home-PC +call %MTOA_LOCATION%\bin\kick.exe %~dp0texture_random.ass diff --git a/tests/volume.ass b/tests/volume.ass new file mode 100644 index 0000000..fbd77ca --- /dev/null +++ b/tests/volume.ass @@ -0,0 +1,40 @@ +### exported: Wed Dec 23 20:59:22 2020 +### from: Arnold 5.1.1.1 [3849b993] windows icc-17.0.2 oiio-1.7.17 osl-1.9.0 vdb-4.0.0 clm-1.0.3.513 rlm-12.2.2 2018/06/26 21:12:06 +### host app: MtoA 3.0.1.1 443e943e (master) Maya 2018 +### user: indigo +### render_layer: defaultRenderLayer +### scene: C:/workspace/apShaders/tests/volume.ma + + + +apVolume +{ + name aiVolumeShape + visibility 255 + matrix + 1 0 0 0 + 0 1 0 0 + 0 0 1 0 + 0 0 0 1 + shader "aiStandardVolume1" + motion_start -0.25 + motion_end 0.25 + id 3558856632 + volume_padding 0 + step_size 0 + filename "C:/workspace/apShaders/tests/wdas_cloud_eighth.vdb" + step_scale 1 + compress on + grids "density" + velocity_scale 1 + velocity_fps 24 + velocity_outlier_threshold 0.00100000005 + declare maya_full_name constant STRING + maya_full_name "|aiVolume|aiVolumeShape" +} + +standard_volume +{ + name aiStandardVolume1 +} + diff --git a/tests/volume.ma b/tests/volume.ma new file mode 100644 index 0000000..cc437b2 --- /dev/null +++ b/tests/volume.ma @@ -0,0 +1,314 @@ +//Maya ASCII 2018ff08 scene +//Name: volume.ma +//Last modified: Tue, Dec 01, 2020 11:01:39 PM +//Codeset: 950 +requires maya "2018ff08"; +requires -nodeType "aiStandIn" -nodeType "aiVolume" -nodeType "aiOptions" -nodeType "aiAOVDriver" + -nodeType "aiAOVFilter" -nodeType "aiStandardVolume" "mtoa" "3.0.1.1"; +requires "stereoCamera" "10.0"; +requires "stereoCamera" "10.0"; +currentUnit -l centimeter -a degree -t film; +fileInfo "application" "maya"; +fileInfo "product" "Maya 2018"; +fileInfo "version" "2018"; +fileInfo "cutIdentifier" "201804211841-f3d65dda2a"; +fileInfo "osv" "Microsoft Windows 8 Business Edition, 64-bit (Build 9200)\n"; +createNode transform -s -n "persp"; + rename -uid "540BF0F1-4578-73C9-90F2-16A70B4482C8"; + setAttr ".v" no; + setAttr ".t" -type "double3" 907.32521816909571 371.34581845320491 568.05484509432665 ; + setAttr ".r" -type "double3" -16.538352729602913 56.200000000000756 4.288036692420017e-15 ; +createNode camera -s -n "perspShape" -p "persp"; + rename -uid "7CC0298F-449F-9C0B-9B5B-DC9B45FD057F"; + setAttr -k off ".v" no; + setAttr ".fl" 34.999999999999993; + setAttr ".coi" 1124.1508731919507; + setAttr ".imn" -type "string" "persp"; + setAttr ".den" -type "string" "persp_depth"; + setAttr ".man" -type "string" "persp_mask"; + setAttr ".hc" -type "string" "viewSet -p %camera"; + setAttr ".ai_translator" -type "string" "perspective"; +createNode transform -s -n "top"; + rename -uid "95F345B7-4D44-1571-A269-1BAE90A6794A"; + setAttr ".v" no; + setAttr ".t" -type "double3" 0 1000.1 0 ; + setAttr ".r" -type "double3" -89.999999999999986 0 0 ; +createNode camera -s -n "topShape" -p "top"; + rename -uid "8181C152-4344-7338-4B53-1F8A42D1C289"; + setAttr -k off ".v" no; + setAttr ".rnd" no; + setAttr ".coi" 1000.1; + setAttr ".ow" 30; + setAttr ".imn" -type "string" "top"; + setAttr ".den" -type "string" "top_depth"; + setAttr ".man" -type "string" "top_mask"; + setAttr ".hc" -type "string" "viewSet -t %camera"; + setAttr ".o" yes; + setAttr ".ai_translator" -type "string" "orthographic"; +createNode transform -s -n "front"; + rename -uid "E0A4C02B-479C-9BF5-7C5A-04A4F98319E0"; + setAttr ".v" no; + setAttr ".t" -type "double3" 0 0 1000.1 ; +createNode camera -s -n "frontShape" -p "front"; + rename -uid "4218DBBC-45B7-E821-8D9D-9EB6513E8BDD"; + setAttr -k off ".v" no; + setAttr ".rnd" no; + setAttr ".coi" 1000.1; + setAttr ".ow" 30; + setAttr ".imn" -type "string" "front"; + setAttr ".den" -type "string" "front_depth"; + setAttr ".man" -type "string" "front_mask"; + setAttr ".hc" -type "string" "viewSet -f %camera"; + setAttr ".o" yes; + setAttr ".ai_translator" -type "string" "orthographic"; +createNode transform -s -n "side"; + rename -uid "A065CF5E-4C5A-3638-6549-D3AFDF410ADB"; + setAttr ".v" no; + setAttr ".t" -type "double3" 1000.1 0 0 ; + setAttr ".r" -type "double3" 0 89.999999999999986 0 ; +createNode camera -s -n "sideShape" -p "side"; + rename -uid "9E85CD03-4BFA-7486-904D-54AAE9FB7890"; + setAttr -k off ".v" no; + setAttr ".rnd" no; + setAttr ".coi" 1000.1; + setAttr ".ow" 30; + setAttr ".imn" -type "string" "side"; + setAttr ".den" -type "string" "side_depth"; + setAttr ".man" -type "string" "side_mask"; + setAttr ".hc" -type "string" "viewSet -s %camera"; + setAttr ".o" yes; + setAttr ".ai_translator" -type "string" "orthographic"; +createNode transform -n "aiVolume"; + rename -uid "3E2A6000-4CF8-0356-5E29-91B996F0F947"; + setAttr ".v" no; +createNode aiVolume -n "aiVolumeShape" -p "aiVolume"; + rename -uid "FF4918C8-4385-5D2B-C63C-19A2123B9D17"; + setAttr -k off ".v"; + setAttr ".covm[0]" 0 1 1; + setAttr ".cdvm[0]" 0 1 1; + setAttr ".filename" -type "string" "C:/workspace/apShaders/tests/wdas_cloud_eighth.vdb"; + setAttr ".grids" -type "string" "density"; +createNode transform -n "directionalLight1"; + rename -uid "4861CB23-41C3-F329-6683-07B31A3D4EDF"; + setAttr ".r" -type "double3" -149.74672424469196 72.19386181707992 -167.94424950871243 ; + setAttr ".s" -type "double3" 293.96008392202691 293.96008392202691 293.96008392202691 ; +createNode directionalLight -n "directionalLightShape1rer" -p "directionalLight1"; + rename -uid "F5AF23D6-475A-0BB4-196D-22BED8B792E9"; + setAttr -k off ".v"; +createNode transform -n "directionalLight2"; + rename -uid "59B87A8B-421D-05D2-16A1-F7B1BCA8529C"; + setAttr ".r" -type "double3" -37.991190800899311 3.2496711148284745 18.774247926898752 ; + setAttr ".s" -type "double3" 427.56812984182358 427.56812984182358 427.56812984182358 ; +createNode directionalLight -n "directionalLightShape2" -p "directionalLight2"; + rename -uid "B86600DB-4AAA-EBFB-CE65-0B955AB882C2"; + setAttr -k off ".v"; +createNode transform -n "aiStandIn"; + rename -uid "D010FBDE-4C61-BA81-40D7-A090F52E2985"; +createNode aiStandIn -n "aiStandInShape" -p "aiStandIn"; + rename -uid "78C4645E-4ADB-0E77-9772-839CA5F59F18"; + setAttr -k off ".v"; + setAttr ".covm[0]" 0 1 1; + setAttr ".cdvm[0]" 0 1 1; + setAttr ".dso" -type "string" "C:/workspace/apShaders/tests/volume.ass"; + setAttr ".overrideCastsShadows" yes; + setAttr ".overridePrimaryVisibility" yes; + setAttr ".overrideVisibleInDiffuseReflection" yes; + setAttr ".overrideVisibleInSpecularReflection" yes; + setAttr ".overrideVisibleInDiffuseTransmission" yes; + setAttr ".overrideVisibleInSpecularTransmission" yes; + setAttr ".overrideVisibleInVolume" yes; +createNode transform -n "pSphere1"; + rename -uid "E3D3F048-43BC-C84D-2389-E1835C413D54"; + setAttr ".t" -type "double3" 0 0 -503.26146675499803 ; + setAttr ".s" -type "double3" 171.24736160951528 171.24736160951528 171.24736160951528 ; +createNode mesh -n "pSphereShape1" -p "pSphere1"; + rename -uid "CB08C77E-4970-B4DA-A001-01A95F7D637B"; + setAttr -k off ".v"; + setAttr ".vir" yes; + setAttr ".vif" yes; + setAttr ".uvst[0].uvsn" -type "string" "map1"; + setAttr ".cuvs" -type "string" "map1"; + setAttr ".dcc" -type "string" "Ambient+Diffuse"; + setAttr ".covm[0]" 0 1 1; + setAttr ".cdvm[0]" 0 1 1; + setAttr ".ai_translator" -type "string" "polymesh"; +createNode lightLinker -s -n "lightLinker1"; + rename -uid "76EFD0D7-49CF-5B1F-0D6D-6DB25D8D3A75"; + setAttr -s 4 ".lnk"; + setAttr -s 3 ".slnk"; +createNode shapeEditorManager -n "shapeEditorManager"; + rename -uid "CFA41937-415B-6313-4563-0EB919A54466"; +createNode poseInterpolatorManager -n "poseInterpolatorManager"; + rename -uid "29B86FDC-4094-1DD2-414D-36AD1FC76DEF"; +createNode displayLayerManager -n "layerManager"; + rename -uid "4D2AFE76-4568-349C-6115-0DB064EDC999"; +createNode displayLayer -n "defaultLayer"; + rename -uid "FA7F4A24-40A7-6C3D-96C1-D09674317655"; +createNode renderLayerManager -n "renderLayerManager"; + rename -uid "97A72346-475C-4F50-7BD7-82A88FB29CF2"; +createNode renderLayer -n "defaultRenderLayer"; + rename -uid "51C3CB87-495F-AC5A-0482-609DE9E352C1"; + setAttr ".g" yes; +createNode aiStandardVolume -n "aiStandardVolume1"; + rename -uid "46BEAB44-4056-9CC3-F1DD-D8876AEE0CA5"; +createNode aiOptions -s -n "defaultArnoldRenderOptions"; + rename -uid "EB724FC2-4F65-F538-6986-40B59087DA0D"; + addAttr -ci true -sn "ARV_options" -ln "ARV_options" -dt "string"; + setAttr ".logv" 3; + setAttr ".version" -type "string" "3.0.1.1"; + setAttr ".ARV_options" -type "string" "Test Resolution=100%;Camera=perspShape;Color Management.Gamma=1;Color Management.Exposure=0;Background.BG=BG Color;Background.Color=0 0 0;Background.Image=;Background.Scale=1 1;Background.Offset=0 0;Background.Apply Color Management=1;Foreground.Enable FG=0;Foreground.Image=;Foreground.Scale=1 1;Foreground.Offset=0 0;Foreground.Apply Color Management=1;"; +createNode aiAOVFilter -s -n "defaultArnoldFilter"; + rename -uid "83997FC4-44CE-C077-4A83-1CA9C90F5921"; + setAttr ".ai_translator" -type "string" "gaussian"; +createNode aiAOVDriver -s -n "defaultArnoldDriver"; + rename -uid "7A24169D-437E-9AEE-1915-A9A8FF811A83"; + setAttr ".ai_translator" -type "string" "exr"; +createNode aiAOVDriver -s -n "defaultArnoldDisplayDriver"; + rename -uid "099E8228-47EC-81C6-E8D6-64B2F61841FE"; + setAttr ".output_mode" 0; + setAttr ".ai_translator" -type "string" "maya"; +createNode shadingEngine -n "aiStandardVolume1SG"; + rename -uid "86605357-4E5B-AC24-A12C-919595D76740"; + setAttr ".ihi" 0; + setAttr ".ro" yes; +createNode materialInfo -n "materialInfo1"; + rename -uid "8A957911-44D6-B76F-2115-49809B0D9BAB"; +createNode nodeGraphEditorInfo -n "hyperShadePrimaryNodeEditorSavedTabsInfo"; + rename -uid "2B4022A7-4847-4F4D-F6BD-D09A1DF8CDB1"; + setAttr ".tgi[0].tn" -type "string" "Untitled_1"; + setAttr ".tgi[0].vl" -type "double2" -203.97792453111478 -587.61612066881628 ; + setAttr ".tgi[0].vh" -type "double2" -28.977931484989707 522.13993279441581 ; + setAttr -s 3 ".tgi[0].ni"; + setAttr ".tgi[0].ni[0].x" 58.571430206298828; + setAttr ".tgi[0].ni[0].y" 25.714284896850586; + setAttr ".tgi[0].ni[0].nvs" 2066; + setAttr ".tgi[0].ni[1].x" -204.28572082519531; + setAttr ".tgi[0].ni[1].y" 168.57142639160156; + setAttr ".tgi[0].ni[1].nvs" 1923; + setAttr ".tgi[0].ni[2].x" 102.85713958740234; + setAttr ".tgi[0].ni[2].y" 191.42857360839844; + setAttr ".tgi[0].ni[2].nvs" 1923; +createNode script -n "uiConfigurationScriptNode"; + rename -uid "043543A5-4602-6669-6997-76A2F2AA3CEE"; + setAttr ".b" -type "string" ( + "// Maya Mel UI Configuration File.\n//\n// This script is machine generated. Edit at your own risk.\n//\n//\n\nglobal string $gMainPane;\nif (`paneLayout -exists $gMainPane`) {\n\n\tglobal int $gUseScenePanelConfig;\n\tint $useSceneConfig = $gUseScenePanelConfig;\n\tint $nodeEditorPanelVisible = stringArrayContains(\"nodeEditorPanel1\", `getPanel -vis`);\n\tint $nodeEditorWorkspaceControlOpen = (`workspaceControl -exists nodeEditorPanel1Window` && `workspaceControl -q -visible nodeEditorPanel1Window`);\n\tint $menusOkayInPanels = `optionVar -q allowMenusInPanels`;\n\tint $nVisPanes = `paneLayout -q -nvp $gMainPane`;\n\tint $nPanes = 0;\n\tstring $editorName;\n\tstring $panelName;\n\tstring $itemFilterName;\n\tstring $panelConfig;\n\n\t//\n\t// get current state of the UI\n\t//\n\tsceneUIReplacement -update $gMainPane;\n\n\t$panelName = `sceneUIReplacement -getNextPanel \"modelPanel\" (localizedPanelLabel(\"Top View\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tmodelPanel -edit -l (localizedPanelLabel(\"Top View\")) -mbv $menusOkayInPanels $panelName;\n" + + "\t\t$editorName = $panelName;\n modelEditor -e \n -camera \"top\" \n -useInteractiveMode 0\n -displayLights \"default\" \n -displayAppearance \"smoothShaded\" \n -activeOnly 0\n -ignorePanZoom 0\n -wireframeOnShaded 0\n -headsUpDisplay 1\n -holdOuts 1\n -selectionHiliteDisplay 1\n -useDefaultMaterial 0\n -bufferMode \"double\" \n -twoSidedLighting 0\n -backfaceCulling 0\n -xray 0\n -jointXray 0\n -activeComponentsXray 0\n -displayTextures 0\n -smoothWireframe 0\n -lineWidth 1\n -textureAnisotropic 0\n -textureHilight 1\n -textureSampling 2\n -textureDisplay \"modulate\" \n -textureMaxSize 32768\n -fogging 0\n -fogSource \"fragment\" \n -fogMode \"linear\" \n -fogStart 0\n -fogEnd 100\n -fogDensity 0.1\n -fogColor 0.5 0.5 0.5 1 \n" + + " -depthOfFieldPreview 1\n -maxConstantTransparency 1\n -rendererName \"vp2Renderer\" \n -objectFilterShowInHUD 1\n -isFiltered 0\n -colorResolution 256 256 \n -bumpResolution 512 512 \n -textureCompression 0\n -transparencyAlgorithm \"frontAndBackCull\" \n -transpInShadows 0\n -cullingOverride \"none\" \n -lowQualityLighting 0\n -maximumNumHardwareLights 1\n -occlusionCulling 0\n -shadingModel 0\n -useBaseRenderer 0\n -useReducedRenderer 0\n -smallObjectCulling 0\n -smallObjectThreshold -1 \n -interactiveDisableShadows 0\n -interactiveBackFaceCull 0\n -sortTransparent 1\n -controllers 1\n -nurbsCurves 1\n -nurbsSurfaces 1\n -polymeshes 1\n -subdivSurfaces 1\n -planes 1\n -lights 1\n -cameras 1\n -controlVertices 1\n" + + " -hulls 1\n -grid 1\n -imagePlane 1\n -joints 1\n -ikHandles 1\n -deformers 1\n -dynamics 1\n -particleInstancers 1\n -fluids 1\n -hairSystems 1\n -follicles 1\n -nCloths 1\n -nParticles 1\n -nRigids 1\n -dynamicConstraints 1\n -locators 1\n -manipulators 1\n -pluginShapes 1\n -dimensions 1\n -handles 1\n -pivots 1\n -textures 1\n -strokes 1\n -motionTrails 1\n -clipGhosts 1\n -greasePencils 1\n -shadows 0\n -captureSequenceNumber -1\n -width 1\n -height 1\n -sceneRenderFilter 0\n $editorName;\n modelEditor -e -viewSelected 0 $editorName;\n modelEditor -e \n -pluginObjects \"gpuCacheDisplayFilter\" 1 \n $editorName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n" + + "\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextPanel \"modelPanel\" (localizedPanelLabel(\"Side View\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tmodelPanel -edit -l (localizedPanelLabel(\"Side View\")) -mbv $menusOkayInPanels $panelName;\n\t\t$editorName = $panelName;\n modelEditor -e \n -camera \"side\" \n -useInteractiveMode 0\n -displayLights \"default\" \n -displayAppearance \"smoothShaded\" \n -activeOnly 0\n -ignorePanZoom 0\n -wireframeOnShaded 0\n -headsUpDisplay 1\n -holdOuts 1\n -selectionHiliteDisplay 1\n -useDefaultMaterial 0\n -bufferMode \"double\" \n -twoSidedLighting 0\n -backfaceCulling 0\n -xray 0\n -jointXray 0\n -activeComponentsXray 0\n -displayTextures 0\n -smoothWireframe 0\n -lineWidth 1\n -textureAnisotropic 0\n -textureHilight 1\n -textureSampling 2\n" + + " -textureDisplay \"modulate\" \n -textureMaxSize 32768\n -fogging 0\n -fogSource \"fragment\" \n -fogMode \"linear\" \n -fogStart 0\n -fogEnd 100\n -fogDensity 0.1\n -fogColor 0.5 0.5 0.5 1 \n -depthOfFieldPreview 1\n -maxConstantTransparency 1\n -rendererName \"vp2Renderer\" \n -objectFilterShowInHUD 1\n -isFiltered 0\n -colorResolution 256 256 \n -bumpResolution 512 512 \n -textureCompression 0\n -transparencyAlgorithm \"frontAndBackCull\" \n -transpInShadows 0\n -cullingOverride \"none\" \n -lowQualityLighting 0\n -maximumNumHardwareLights 1\n -occlusionCulling 0\n -shadingModel 0\n -useBaseRenderer 0\n -useReducedRenderer 0\n -smallObjectCulling 0\n -smallObjectThreshold -1 \n -interactiveDisableShadows 0\n -interactiveBackFaceCull 0\n" + + " -sortTransparent 1\n -controllers 1\n -nurbsCurves 1\n -nurbsSurfaces 1\n -polymeshes 1\n -subdivSurfaces 1\n -planes 1\n -lights 1\n -cameras 1\n -controlVertices 1\n -hulls 1\n -grid 1\n -imagePlane 1\n -joints 1\n -ikHandles 1\n -deformers 1\n -dynamics 1\n -particleInstancers 1\n -fluids 1\n -hairSystems 1\n -follicles 1\n -nCloths 1\n -nParticles 1\n -nRigids 1\n -dynamicConstraints 1\n -locators 1\n -manipulators 1\n -pluginShapes 1\n -dimensions 1\n -handles 1\n -pivots 1\n -textures 1\n -strokes 1\n -motionTrails 1\n -clipGhosts 1\n -greasePencils 1\n -shadows 0\n -captureSequenceNumber -1\n -width 1\n -height 1\n" + + " -sceneRenderFilter 0\n $editorName;\n modelEditor -e -viewSelected 0 $editorName;\n modelEditor -e \n -pluginObjects \"gpuCacheDisplayFilter\" 1 \n $editorName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextPanel \"modelPanel\" (localizedPanelLabel(\"Front View\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tmodelPanel -edit -l (localizedPanelLabel(\"Front View\")) -mbv $menusOkayInPanels $panelName;\n\t\t$editorName = $panelName;\n modelEditor -e \n -camera \"front\" \n -useInteractiveMode 0\n -displayLights \"default\" \n -displayAppearance \"smoothShaded\" \n -activeOnly 0\n -ignorePanZoom 0\n -wireframeOnShaded 0\n -headsUpDisplay 1\n -holdOuts 1\n -selectionHiliteDisplay 1\n -useDefaultMaterial 0\n -bufferMode \"double\" \n -twoSidedLighting 0\n -backfaceCulling 0\n" + + " -xray 0\n -jointXray 0\n -activeComponentsXray 0\n -displayTextures 0\n -smoothWireframe 0\n -lineWidth 1\n -textureAnisotropic 0\n -textureHilight 1\n -textureSampling 2\n -textureDisplay \"modulate\" \n -textureMaxSize 32768\n -fogging 0\n -fogSource \"fragment\" \n -fogMode \"linear\" \n -fogStart 0\n -fogEnd 100\n -fogDensity 0.1\n -fogColor 0.5 0.5 0.5 1 \n -depthOfFieldPreview 1\n -maxConstantTransparency 1\n -rendererName \"vp2Renderer\" \n -objectFilterShowInHUD 1\n -isFiltered 0\n -colorResolution 256 256 \n -bumpResolution 512 512 \n -textureCompression 0\n -transparencyAlgorithm \"frontAndBackCull\" \n -transpInShadows 0\n -cullingOverride \"none\" \n -lowQualityLighting 0\n -maximumNumHardwareLights 1\n -occlusionCulling 0\n" + + " -shadingModel 0\n -useBaseRenderer 0\n -useReducedRenderer 0\n -smallObjectCulling 0\n -smallObjectThreshold -1 \n -interactiveDisableShadows 0\n -interactiveBackFaceCull 0\n -sortTransparent 1\n -controllers 1\n -nurbsCurves 1\n -nurbsSurfaces 1\n -polymeshes 1\n -subdivSurfaces 1\n -planes 1\n -lights 1\n -cameras 1\n -controlVertices 1\n -hulls 1\n -grid 1\n -imagePlane 1\n -joints 1\n -ikHandles 1\n -deformers 1\n -dynamics 1\n -particleInstancers 1\n -fluids 1\n -hairSystems 1\n -follicles 1\n -nCloths 1\n -nParticles 1\n -nRigids 1\n -dynamicConstraints 1\n -locators 1\n -manipulators 1\n -pluginShapes 1\n -dimensions 1\n -handles 1\n -pivots 1\n" + + " -textures 1\n -strokes 1\n -motionTrails 1\n -clipGhosts 1\n -greasePencils 1\n -shadows 0\n -captureSequenceNumber -1\n -width 1\n -height 1\n -sceneRenderFilter 0\n $editorName;\n modelEditor -e -viewSelected 0 $editorName;\n modelEditor -e \n -pluginObjects \"gpuCacheDisplayFilter\" 1 \n $editorName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextPanel \"modelPanel\" (localizedPanelLabel(\"Persp View\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tmodelPanel -edit -l (localizedPanelLabel(\"Persp View\")) -mbv $menusOkayInPanels $panelName;\n\t\t$editorName = $panelName;\n modelEditor -e \n -camera \"persp\" \n -useInteractiveMode 0\n -displayLights \"default\" \n -displayAppearance \"smoothShaded\" \n -activeOnly 0\n -ignorePanZoom 0\n" + + " -wireframeOnShaded 0\n -headsUpDisplay 1\n -holdOuts 1\n -selectionHiliteDisplay 1\n -useDefaultMaterial 0\n -bufferMode \"double\" \n -twoSidedLighting 0\n -backfaceCulling 0\n -xray 0\n -jointXray 0\n -activeComponentsXray 0\n -displayTextures 0\n -smoothWireframe 0\n -lineWidth 1\n -textureAnisotropic 0\n -textureHilight 1\n -textureSampling 2\n -textureDisplay \"modulate\" \n -textureMaxSize 32768\n -fogging 0\n -fogSource \"fragment\" \n -fogMode \"linear\" \n -fogStart 0\n -fogEnd 100\n -fogDensity 0.1\n -fogColor 0.5 0.5 0.5 1 \n -depthOfFieldPreview 1\n -maxConstantTransparency 1\n -rendererName \"vp2Renderer\" \n -objectFilterShowInHUD 1\n -isFiltered 0\n -colorResolution 256 256 \n -bumpResolution 512 512 \n" + + " -textureCompression 0\n -transparencyAlgorithm \"frontAndBackCull\" \n -transpInShadows 0\n -cullingOverride \"none\" \n -lowQualityLighting 0\n -maximumNumHardwareLights 1\n -occlusionCulling 0\n -shadingModel 0\n -useBaseRenderer 0\n -useReducedRenderer 0\n -smallObjectCulling 0\n -smallObjectThreshold -1 \n -interactiveDisableShadows 0\n -interactiveBackFaceCull 0\n -sortTransparent 1\n -controllers 1\n -nurbsCurves 1\n -nurbsSurfaces 1\n -polymeshes 1\n -subdivSurfaces 1\n -planes 1\n -lights 1\n -cameras 1\n -controlVertices 1\n -hulls 1\n -grid 1\n -imagePlane 1\n -joints 1\n -ikHandles 1\n -deformers 1\n -dynamics 1\n -particleInstancers 1\n -fluids 1\n -hairSystems 1\n -follicles 1\n" + + " -nCloths 1\n -nParticles 1\n -nRigids 1\n -dynamicConstraints 1\n -locators 1\n -manipulators 1\n -pluginShapes 1\n -dimensions 1\n -handles 1\n -pivots 1\n -textures 1\n -strokes 1\n -motionTrails 1\n -clipGhosts 1\n -greasePencils 1\n -shadows 0\n -captureSequenceNumber -1\n -width 1562\n -height 830\n -sceneRenderFilter 0\n $editorName;\n modelEditor -e -viewSelected 0 $editorName;\n modelEditor -e \n -pluginObjects \"gpuCacheDisplayFilter\" 1 \n $editorName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextPanel \"outlinerPanel\" (localizedPanelLabel(\"ToggledOutliner\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\toutlinerPanel -edit -l (localizedPanelLabel(\"ToggledOutliner\")) -mbv $menusOkayInPanels $panelName;\n" + + "\t\t$editorName = $panelName;\n outlinerEditor -e \n -showShapes 0\n -showAssignedMaterials 0\n -showTimeEditor 1\n -showReferenceNodes 1\n -showReferenceMembers 1\n -showAttributes 0\n -showConnected 0\n -showAnimCurvesOnly 0\n -showMuteInfo 0\n -organizeByLayer 1\n -organizeByClip 1\n -showAnimLayerWeight 1\n -autoExpandLayers 1\n -autoExpand 0\n -showDagOnly 0\n -showAssets 1\n -showContainedOnly 1\n -showPublishedAsConnected 0\n -showParentContainers 0\n -showContainerContents 1\n -ignoreDagHierarchy 0\n -expandConnections 0\n -showUpstreamCurves 1\n -showUnitlessCurves 1\n -showCompounds 1\n -showLeafs 1\n -showNumericAttrsOnly 0\n -highlightActive 1\n -autoSelectNewObjects 0\n -doNotSelectNewObjects 0\n -dropIsParent 1\n" + + " -transmitFilters 0\n -setFilter \"defaultSetFilter\" \n -showSetMembers 1\n -allowMultiSelection 1\n -alwaysToggleSelect 0\n -directSelect 0\n -isSet 0\n -isSetMember 0\n -displayMode \"DAG\" \n -expandObjects 0\n -setsIgnoreFilters 1\n -containersIgnoreFilters 0\n -editAttrName 0\n -showAttrValues 0\n -highlightSecondary 0\n -showUVAttrsOnly 0\n -showTextureNodesOnly 0\n -attrAlphaOrder \"default\" \n -animLayerFilterOptions \"allAffecting\" \n -sortOrder \"none\" \n -longNames 0\n -niceNames 1\n -showNamespace 1\n -showPinIcons 0\n -mapMotionTrails 0\n -ignoreHiddenAttribute 0\n -ignoreOutlinerColor 0\n -renderFilterVisible 0\n -renderFilterIndex 0\n -selectionOrder \"chronological\" \n -expandAttribute 0\n $editorName;\n" + + "\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextPanel \"outlinerPanel\" (localizedPanelLabel(\"Outliner\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\toutlinerPanel -edit -l (localizedPanelLabel(\"Outliner\")) -mbv $menusOkayInPanels $panelName;\n\t\t$editorName = $panelName;\n outlinerEditor -e \n -showShapes 0\n -showAssignedMaterials 0\n -showTimeEditor 1\n -showReferenceNodes 0\n -showReferenceMembers 0\n -showAttributes 0\n -showConnected 0\n -showAnimCurvesOnly 0\n -showMuteInfo 0\n -organizeByLayer 1\n -organizeByClip 1\n -showAnimLayerWeight 1\n -autoExpandLayers 1\n -autoExpand 0\n -showDagOnly 1\n -showAssets 1\n -showContainedOnly 1\n -showPublishedAsConnected 0\n -showParentContainers 0\n -showContainerContents 1\n -ignoreDagHierarchy 0\n" + + " -expandConnections 0\n -showUpstreamCurves 1\n -showUnitlessCurves 1\n -showCompounds 1\n -showLeafs 1\n -showNumericAttrsOnly 0\n -highlightActive 1\n -autoSelectNewObjects 0\n -doNotSelectNewObjects 0\n -dropIsParent 1\n -transmitFilters 0\n -setFilter \"defaultSetFilter\" \n -showSetMembers 1\n -allowMultiSelection 1\n -alwaysToggleSelect 0\n -directSelect 0\n -displayMode \"DAG\" \n -expandObjects 0\n -setsIgnoreFilters 1\n -containersIgnoreFilters 0\n -editAttrName 0\n -showAttrValues 0\n -highlightSecondary 0\n -showUVAttrsOnly 0\n -showTextureNodesOnly 0\n -attrAlphaOrder \"default\" \n -animLayerFilterOptions \"allAffecting\" \n -sortOrder \"none\" \n -longNames 0\n -niceNames 1\n -showNamespace 1\n -showPinIcons 0\n" + + " -mapMotionTrails 0\n -ignoreHiddenAttribute 0\n -ignoreOutlinerColor 0\n -renderFilterVisible 0\n $editorName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"graphEditor\" (localizedPanelLabel(\"Graph Editor\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Graph Editor\")) -mbv $menusOkayInPanels $panelName;\n\n\t\t\t$editorName = ($panelName+\"OutlineEd\");\n outlinerEditor -e \n -showShapes 1\n -showAssignedMaterials 0\n -showTimeEditor 1\n -showReferenceNodes 0\n -showReferenceMembers 0\n -showAttributes 1\n -showConnected 1\n -showAnimCurvesOnly 1\n -showMuteInfo 0\n -organizeByLayer 1\n -organizeByClip 1\n -showAnimLayerWeight 1\n -autoExpandLayers 1\n" + + " -autoExpand 1\n -showDagOnly 0\n -showAssets 1\n -showContainedOnly 0\n -showPublishedAsConnected 0\n -showParentContainers 1\n -showContainerContents 0\n -ignoreDagHierarchy 0\n -expandConnections 1\n -showUpstreamCurves 1\n -showUnitlessCurves 1\n -showCompounds 0\n -showLeafs 1\n -showNumericAttrsOnly 1\n -highlightActive 0\n -autoSelectNewObjects 1\n -doNotSelectNewObjects 0\n -dropIsParent 1\n -transmitFilters 1\n -setFilter \"0\" \n -showSetMembers 0\n -allowMultiSelection 1\n -alwaysToggleSelect 0\n -directSelect 0\n -displayMode \"DAG\" \n -expandObjects 0\n -setsIgnoreFilters 1\n -containersIgnoreFilters 0\n -editAttrName 0\n" + + " -showAttrValues 0\n -highlightSecondary 0\n -showUVAttrsOnly 0\n -showTextureNodesOnly 0\n -attrAlphaOrder \"default\" \n -animLayerFilterOptions \"allAffecting\" \n -sortOrder \"none\" \n -longNames 0\n -niceNames 1\n -showNamespace 1\n -showPinIcons 1\n -mapMotionTrails 1\n -ignoreHiddenAttribute 0\n -ignoreOutlinerColor 0\n -renderFilterVisible 0\n $editorName;\n\n\t\t\t$editorName = ($panelName+\"GraphEd\");\n animCurveEditor -e \n -displayKeys 1\n -displayTangents 0\n -displayActiveKeys 0\n -displayActiveKeyTangents 1\n -displayInfinities 0\n -displayValues 0\n -autoFit 1\n -autoFitTime 0\n -snapTime \"integer\" \n -snapValue \"none\" \n -showResults \"off\" \n" + + " -showBufferCurves \"off\" \n -smoothness \"fine\" \n -resultSamples 1\n -resultScreenSamples 0\n -resultUpdate \"delayed\" \n -showUpstreamCurves 1\n -showCurveNames 0\n -showActiveCurveNames 0\n -stackedCurves 0\n -stackedCurvesMin -1\n -stackedCurvesMax 1\n -stackedCurvesSpace 0.2\n -displayNormalized 0\n -preSelectionHighlight 0\n -constrainDrag 0\n -classicMode 1\n -valueLinesToggle 1\n $editorName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"dopeSheetPanel\" (localizedPanelLabel(\"Dope Sheet\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Dope Sheet\")) -mbv $menusOkayInPanels $panelName;\n\n\t\t\t$editorName = ($panelName+\"OutlineEd\");\n" + + " outlinerEditor -e \n -showShapes 1\n -showAssignedMaterials 0\n -showTimeEditor 1\n -showReferenceNodes 0\n -showReferenceMembers 0\n -showAttributes 1\n -showConnected 1\n -showAnimCurvesOnly 1\n -showMuteInfo 0\n -organizeByLayer 1\n -organizeByClip 1\n -showAnimLayerWeight 1\n -autoExpandLayers 1\n -autoExpand 0\n -showDagOnly 0\n -showAssets 1\n -showContainedOnly 0\n -showPublishedAsConnected 0\n -showParentContainers 1\n -showContainerContents 0\n -ignoreDagHierarchy 0\n -expandConnections 1\n -showUpstreamCurves 1\n -showUnitlessCurves 0\n -showCompounds 1\n -showLeafs 1\n -showNumericAttrsOnly 1\n -highlightActive 0\n" + + " -autoSelectNewObjects 0\n -doNotSelectNewObjects 1\n -dropIsParent 1\n -transmitFilters 0\n -setFilter \"0\" \n -showSetMembers 0\n -allowMultiSelection 1\n -alwaysToggleSelect 0\n -directSelect 0\n -displayMode \"DAG\" \n -expandObjects 0\n -setsIgnoreFilters 1\n -containersIgnoreFilters 0\n -editAttrName 0\n -showAttrValues 0\n -highlightSecondary 0\n -showUVAttrsOnly 0\n -showTextureNodesOnly 0\n -attrAlphaOrder \"default\" \n -animLayerFilterOptions \"allAffecting\" \n -sortOrder \"none\" \n -longNames 0\n -niceNames 1\n -showNamespace 1\n -showPinIcons 0\n -mapMotionTrails 1\n -ignoreHiddenAttribute 0\n -ignoreOutlinerColor 0\n -renderFilterVisible 0\n" + + " $editorName;\n\n\t\t\t$editorName = ($panelName+\"DopeSheetEd\");\n dopeSheetEditor -e \n -displayKeys 1\n -displayTangents 0\n -displayActiveKeys 0\n -displayActiveKeyTangents 0\n -displayInfinities 0\n -displayValues 0\n -autoFit 0\n -autoFitTime 0\n -snapTime \"integer\" \n -snapValue \"none\" \n -outliner \"dopeSheetPanel1OutlineEd\" \n -showSummary 1\n -showScene 0\n -hierarchyBelow 0\n -showTicks 1\n -selectionWindow 0 0 0 0 \n $editorName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"timeEditorPanel\" (localizedPanelLabel(\"Time Editor\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Time Editor\")) -mbv $menusOkayInPanels $panelName;\n" + + "\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"clipEditorPanel\" (localizedPanelLabel(\"Trax Editor\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Trax Editor\")) -mbv $menusOkayInPanels $panelName;\n\n\t\t\t$editorName = clipEditorNameFromPanel($panelName);\n clipEditor -e \n -displayKeys 0\n -displayTangents 0\n -displayActiveKeys 0\n -displayActiveKeyTangents 0\n -displayInfinities 0\n -displayValues 0\n -autoFit 0\n -autoFitTime 0\n -snapTime \"none\" \n -snapValue \"none\" \n -initialized 0\n -manageSequencer 0 \n $editorName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"sequenceEditorPanel\" (localizedPanelLabel(\"Camera Sequencer\")) `;\n" + + "\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Camera Sequencer\")) -mbv $menusOkayInPanels $panelName;\n\n\t\t\t$editorName = sequenceEditorNameFromPanel($panelName);\n clipEditor -e \n -displayKeys 0\n -displayTangents 0\n -displayActiveKeys 0\n -displayActiveKeyTangents 0\n -displayInfinities 0\n -displayValues 0\n -autoFit 0\n -autoFitTime 0\n -snapTime \"none\" \n -snapValue \"none\" \n -initialized 0\n -manageSequencer 1 \n $editorName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"hyperGraphPanel\" (localizedPanelLabel(\"Hypergraph Hierarchy\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Hypergraph Hierarchy\")) -mbv $menusOkayInPanels $panelName;\n" + + "\n\t\t\t$editorName = ($panelName+\"HyperGraphEd\");\n hyperGraph -e \n -graphLayoutStyle \"hierarchicalLayout\" \n -orientation \"horiz\" \n -mergeConnections 0\n -zoom 1\n -animateTransition 0\n -showRelationships 1\n -showShapes 0\n -showDeformers 0\n -showExpressions 0\n -showConstraints 0\n -showConnectionFromSelected 0\n -showConnectionToSelected 0\n -showConstraintLabels 0\n -showUnderworld 0\n -showInvisible 0\n -transitionFrames 1\n -opaqueContainers 0\n -freeform 0\n -imagePosition 0 0 \n -imageScale 1\n -imageEnabled 0\n -graphType \"DAG\" \n -heatMapDisplay 0\n -updateSelection 1\n -updateNodeAdded 1\n -useDrawOverrideColor 0\n -limitGraphTraversal -1\n" + + " -range 0 0 \n -iconSize \"smallIcons\" \n -showCachedConnections 0\n $editorName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"hyperShadePanel\" (localizedPanelLabel(\"Hypershade\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Hypershade\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"visorPanel\" (localizedPanelLabel(\"Visor\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Visor\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"nodeEditorPanel\" (localizedPanelLabel(\"Node Editor\")) `;\n\tif ($nodeEditorPanelVisible || $nodeEditorWorkspaceControlOpen) {\n" + + "\t\tif (\"\" == $panelName) {\n\t\t\tif ($useSceneConfig) {\n\t\t\t\t$panelName = `scriptedPanel -unParent -type \"nodeEditorPanel\" -l (localizedPanelLabel(\"Node Editor\")) -mbv $menusOkayInPanels `;\n\n\t\t\t$editorName = ($panelName+\"NodeEditorEd\");\n nodeEditor -e \n -allAttributes 0\n -allNodes 0\n -autoSizeNodes 1\n -consistentNameSize 1\n -createNodeCommand \"nodeEdCreateNodeCommand\" \n -connectNodeOnCreation 0\n -connectOnDrop 0\n -copyConnectionsOnPaste 0\n -defaultPinnedState 0\n -additiveGraphingMode 0\n -settingsChangedCallback \"nodeEdSyncControls\" \n -traversalDepthLimit -1\n -keyPressCommand \"nodeEdKeyPressCommand\" \n -nodeTitleMode \"name\" \n -gridSnap 0\n -gridVisibility 1\n -crosshairOnEdgeDragging 0\n -popupMenuScript \"nodeEdBuildPanelMenus\" \n -showNamespace 1\n" + + " -showShapes 1\n -showSGShapes 0\n -showTransforms 1\n -useAssets 1\n -syncedSelection 1\n -extendToShapes 1\n -editorMode \"default\" \n $editorName;\n\t\t\t}\n\t\t} else {\n\t\t\t$label = `panel -q -label $panelName`;\n\t\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Node Editor\")) -mbv $menusOkayInPanels $panelName;\n\n\t\t\t$editorName = ($panelName+\"NodeEditorEd\");\n nodeEditor -e \n -allAttributes 0\n -allNodes 0\n -autoSizeNodes 1\n -consistentNameSize 1\n -createNodeCommand \"nodeEdCreateNodeCommand\" \n -connectNodeOnCreation 0\n -connectOnDrop 0\n -copyConnectionsOnPaste 0\n -defaultPinnedState 0\n -additiveGraphingMode 0\n -settingsChangedCallback \"nodeEdSyncControls\" \n -traversalDepthLimit -1\n -keyPressCommand \"nodeEdKeyPressCommand\" \n" + + " -nodeTitleMode \"name\" \n -gridSnap 0\n -gridVisibility 1\n -crosshairOnEdgeDragging 0\n -popupMenuScript \"nodeEdBuildPanelMenus\" \n -showNamespace 1\n -showShapes 1\n -showSGShapes 0\n -showTransforms 1\n -useAssets 1\n -syncedSelection 1\n -extendToShapes 1\n -editorMode \"default\" \n $editorName;\n\t\t\tif (!$useSceneConfig) {\n\t\t\t\tpanel -e -l $label $panelName;\n\t\t\t}\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"createNodePanel\" (localizedPanelLabel(\"Create Node\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Create Node\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"polyTexturePlacementPanel\" (localizedPanelLabel(\"UV Editor\")) `;\n" + + "\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"UV Editor\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"renderWindowPanel\" (localizedPanelLabel(\"Render View\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Render View\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextPanel \"shapePanel\" (localizedPanelLabel(\"Shape Editor\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tshapePanel -edit -l (localizedPanelLabel(\"Shape Editor\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextPanel \"posePanel\" (localizedPanelLabel(\"Pose Editor\")) `;\n\tif (\"\" != $panelName) {\n" + + "\t\t$label = `panel -q -label $panelName`;\n\t\tposePanel -edit -l (localizedPanelLabel(\"Pose Editor\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"dynRelEdPanel\" (localizedPanelLabel(\"Dynamic Relationships\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Dynamic Relationships\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"relationshipPanel\" (localizedPanelLabel(\"Relationship Editor\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Relationship Editor\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"referenceEditorPanel\" (localizedPanelLabel(\"Reference Editor\")) `;\n" + + "\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Reference Editor\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"componentEditorPanel\" (localizedPanelLabel(\"Component Editor\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Component Editor\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"dynPaintScriptedPanelType\" (localizedPanelLabel(\"Paint Effects\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Paint Effects\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"scriptEditorPanel\" (localizedPanelLabel(\"Script Editor\")) `;\n" + + "\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Script Editor\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"profilerPanel\" (localizedPanelLabel(\"Profiler Tool\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Profiler Tool\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"contentBrowserPanel\" (localizedPanelLabel(\"Content Browser\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Content Browser\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"Stereo\" (localizedPanelLabel(\"Stereo\")) `;\n" + + "\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Stereo\")) -mbv $menusOkayInPanels $panelName;\nstring $editorName = ($panelName+\"Editor\");\n stereoCameraView -e \n -camera \"persp\" \n -useInteractiveMode 0\n -displayLights \"default\" \n -displayAppearance \"wireframe\" \n -activeOnly 0\n -ignorePanZoom 0\n -wireframeOnShaded 0\n -headsUpDisplay 1\n -holdOuts 1\n -selectionHiliteDisplay 1\n -useDefaultMaterial 0\n -bufferMode \"double\" \n -twoSidedLighting 1\n -backfaceCulling 0\n -xray 0\n -jointXray 0\n -activeComponentsXray 0\n -displayTextures 0\n -smoothWireframe 0\n -lineWidth 1\n -textureAnisotropic 0\n -textureHilight 1\n -textureSampling 2\n" + + " -textureDisplay \"modulate\" \n -textureMaxSize 32768\n -fogging 0\n -fogSource \"fragment\" \n -fogMode \"linear\" \n -fogStart 0\n -fogEnd 100\n -fogDensity 0.1\n -fogColor 0.5 0.5 0.5 1 \n -depthOfFieldPreview 1\n -maxConstantTransparency 1\n -objectFilterShowInHUD 1\n -isFiltered 0\n -colorResolution 4 4 \n -bumpResolution 4 4 \n -textureCompression 0\n -transparencyAlgorithm \"frontAndBackCull\" \n -transpInShadows 0\n -cullingOverride \"none\" \n -lowQualityLighting 0\n -maximumNumHardwareLights 0\n -occlusionCulling 0\n -shadingModel 0\n -useBaseRenderer 0\n -useReducedRenderer 0\n -smallObjectCulling 0\n -smallObjectThreshold -1 \n -interactiveDisableShadows 0\n" + + " -interactiveBackFaceCull 0\n -sortTransparent 1\n -controllers 1\n -nurbsCurves 1\n -nurbsSurfaces 1\n -polymeshes 1\n -subdivSurfaces 1\n -planes 1\n -lights 1\n -cameras 1\n -controlVertices 1\n -hulls 1\n -grid 1\n -imagePlane 1\n -joints 1\n -ikHandles 1\n -deformers 1\n -dynamics 1\n -particleInstancers 1\n -fluids 1\n -hairSystems 1\n -follicles 1\n -nCloths 1\n -nParticles 1\n -nRigids 1\n -dynamicConstraints 1\n -locators 1\n -manipulators 1\n -pluginShapes 1\n -dimensions 1\n -handles 1\n -pivots 1\n -textures 1\n -strokes 1\n -motionTrails 1\n" + + " -clipGhosts 1\n -greasePencils 1\n -shadows 0\n -captureSequenceNumber -1\n -width 0\n -height 0\n -sceneRenderFilter 0\n -displayMode \"centerEye\" \n -viewColor 0 0 0 1 \n -useCustomBackground 1\n $editorName;\n stereoCameraView -e -viewSelected 0 $editorName;\n stereoCameraView -e \n -pluginObjects \"gpuCacheDisplayFilter\" 1 \n $editorName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\tif ($useSceneConfig) {\n string $configName = `getPanel -cwl (localizedPanelLabel(\"Current Layout\"))`;\n if (\"\" != $configName) {\n\t\t\tpanelConfiguration -edit -label (localizedPanelLabel(\"Current Layout\")) \n\t\t\t\t-userCreated false\n\t\t\t\t-defaultImage \"\"\n\t\t\t\t-image \"\"\n\t\t\t\t-sc false\n\t\t\t\t-configString \"global string $gMainPane; paneLayout -e -cn \\\"single\\\" -ps 1 100 100 $gMainPane;\"\n\t\t\t\t-removeAllPanels\n" + + "\t\t\t\t-ap false\n\t\t\t\t\t(localizedPanelLabel(\"Persp View\")) \n\t\t\t\t\t\"modelPanel\"\n" + + "\t\t\t\t\t\"$panelName = `modelPanel -unParent -l (localizedPanelLabel(\\\"Persp View\\\")) -mbv $menusOkayInPanels `;\\n$editorName = $panelName;\\nmodelEditor -e \\n -cam `findStartUpCamera persp` \\n -useInteractiveMode 0\\n -displayLights \\\"default\\\" \\n -displayAppearance \\\"smoothShaded\\\" \\n -activeOnly 0\\n -ignorePanZoom 0\\n -wireframeOnShaded 0\\n -headsUpDisplay 1\\n -holdOuts 1\\n -selectionHiliteDisplay 1\\n -useDefaultMaterial 0\\n -bufferMode \\\"double\\\" \\n -twoSidedLighting 0\\n -backfaceCulling 0\\n -xray 0\\n -jointXray 0\\n -activeComponentsXray 0\\n -displayTextures 0\\n -smoothWireframe 0\\n -lineWidth 1\\n -textureAnisotropic 0\\n -textureHilight 1\\n -textureSampling 2\\n -textureDisplay \\\"modulate\\\" \\n -textureMaxSize 32768\\n -fogging 0\\n -fogSource \\\"fragment\\\" \\n -fogMode \\\"linear\\\" \\n -fogStart 0\\n -fogEnd 100\\n -fogDensity 0.1\\n -fogColor 0.5 0.5 0.5 1 \\n -depthOfFieldPreview 1\\n -maxConstantTransparency 1\\n -rendererName \\\"vp2Renderer\\\" \\n -objectFilterShowInHUD 1\\n -isFiltered 0\\n -colorResolution 256 256 \\n -bumpResolution 512 512 \\n -textureCompression 0\\n -transparencyAlgorithm \\\"frontAndBackCull\\\" \\n -transpInShadows 0\\n -cullingOverride \\\"none\\\" \\n -lowQualityLighting 0\\n -maximumNumHardwareLights 1\\n -occlusionCulling 0\\n -shadingModel 0\\n -useBaseRenderer 0\\n -useReducedRenderer 0\\n -smallObjectCulling 0\\n -smallObjectThreshold -1 \\n -interactiveDisableShadows 0\\n -interactiveBackFaceCull 0\\n -sortTransparent 1\\n -controllers 1\\n -nurbsCurves 1\\n -nurbsSurfaces 1\\n -polymeshes 1\\n -subdivSurfaces 1\\n -planes 1\\n -lights 1\\n -cameras 1\\n -controlVertices 1\\n -hulls 1\\n -grid 1\\n -imagePlane 1\\n -joints 1\\n -ikHandles 1\\n -deformers 1\\n -dynamics 1\\n -particleInstancers 1\\n -fluids 1\\n -hairSystems 1\\n -follicles 1\\n -nCloths 1\\n -nParticles 1\\n -nRigids 1\\n -dynamicConstraints 1\\n -locators 1\\n -manipulators 1\\n -pluginShapes 1\\n -dimensions 1\\n -handles 1\\n -pivots 1\\n -textures 1\\n -strokes 1\\n -motionTrails 1\\n -clipGhosts 1\\n -greasePencils 1\\n -shadows 0\\n -captureSequenceNumber -1\\n -width 1562\\n -height 830\\n -sceneRenderFilter 0\\n $editorName;\\nmodelEditor -e -viewSelected 0 $editorName;\\nmodelEditor -e \\n -pluginObjects \\\"gpuCacheDisplayFilter\\\" 1 \\n $editorName\"\n" + + "\t\t\t\t\t\"modelPanel -edit -l (localizedPanelLabel(\\\"Persp View\\\")) -mbv $menusOkayInPanels $panelName;\\n$editorName = $panelName;\\nmodelEditor -e \\n -cam `findStartUpCamera persp` \\n -useInteractiveMode 0\\n -displayLights \\\"default\\\" \\n -displayAppearance \\\"smoothShaded\\\" \\n -activeOnly 0\\n -ignorePanZoom 0\\n -wireframeOnShaded 0\\n -headsUpDisplay 1\\n -holdOuts 1\\n -selectionHiliteDisplay 1\\n -useDefaultMaterial 0\\n -bufferMode \\\"double\\\" \\n -twoSidedLighting 0\\n -backfaceCulling 0\\n -xray 0\\n -jointXray 0\\n -activeComponentsXray 0\\n -displayTextures 0\\n -smoothWireframe 0\\n -lineWidth 1\\n -textureAnisotropic 0\\n -textureHilight 1\\n -textureSampling 2\\n -textureDisplay \\\"modulate\\\" \\n -textureMaxSize 32768\\n -fogging 0\\n -fogSource \\\"fragment\\\" \\n -fogMode \\\"linear\\\" \\n -fogStart 0\\n -fogEnd 100\\n -fogDensity 0.1\\n -fogColor 0.5 0.5 0.5 1 \\n -depthOfFieldPreview 1\\n -maxConstantTransparency 1\\n -rendererName \\\"vp2Renderer\\\" \\n -objectFilterShowInHUD 1\\n -isFiltered 0\\n -colorResolution 256 256 \\n -bumpResolution 512 512 \\n -textureCompression 0\\n -transparencyAlgorithm \\\"frontAndBackCull\\\" \\n -transpInShadows 0\\n -cullingOverride \\\"none\\\" \\n -lowQualityLighting 0\\n -maximumNumHardwareLights 1\\n -occlusionCulling 0\\n -shadingModel 0\\n -useBaseRenderer 0\\n -useReducedRenderer 0\\n -smallObjectCulling 0\\n -smallObjectThreshold -1 \\n -interactiveDisableShadows 0\\n -interactiveBackFaceCull 0\\n -sortTransparent 1\\n -controllers 1\\n -nurbsCurves 1\\n -nurbsSurfaces 1\\n -polymeshes 1\\n -subdivSurfaces 1\\n -planes 1\\n -lights 1\\n -cameras 1\\n -controlVertices 1\\n -hulls 1\\n -grid 1\\n -imagePlane 1\\n -joints 1\\n -ikHandles 1\\n -deformers 1\\n -dynamics 1\\n -particleInstancers 1\\n -fluids 1\\n -hairSystems 1\\n -follicles 1\\n -nCloths 1\\n -nParticles 1\\n -nRigids 1\\n -dynamicConstraints 1\\n -locators 1\\n -manipulators 1\\n -pluginShapes 1\\n -dimensions 1\\n -handles 1\\n -pivots 1\\n -textures 1\\n -strokes 1\\n -motionTrails 1\\n -clipGhosts 1\\n -greasePencils 1\\n -shadows 0\\n -captureSequenceNumber -1\\n -width 1562\\n -height 830\\n -sceneRenderFilter 0\\n $editorName;\\nmodelEditor -e -viewSelected 0 $editorName;\\nmodelEditor -e \\n -pluginObjects \\\"gpuCacheDisplayFilter\\\" 1 \\n $editorName\"\n" + + "\t\t\t\t$configName;\n\n setNamedPanelLayout (localizedPanelLabel(\"Current Layout\"));\n }\n\n panelHistory -e -clear mainPanelHistory;\n sceneUIReplacement -clear;\n\t}\n\n\ngrid -spacing 5 -size 12 -divisions 5 -displayAxes yes -displayGridLines yes -displayDivisionLines yes -displayPerspectiveLabels no -displayOrthographicLabels no -displayAxesBold yes -perspectiveLabelPosition axis -orthographicLabelPosition edge;\nviewManip -drawCompass 0 -compassAngle 0 -frontParameters \"\" -homeParameters \"\" -selectionLockParameters \"\";\n}\n"); + setAttr ".st" 3; +createNode script -n "sceneConfigurationScriptNode"; + rename -uid "97F880CA-4EDC-7338-C02B-6BB6685B67DF"; + setAttr ".b" -type "string" "playbackOptions -min 1 -max 120 -ast 1 -aet 200 "; + setAttr ".st" 6; +createNode objectSet -s -n "ArnoldStandInDefaultLightSet"; + rename -uid "7D28A340-4E6F-EB5B-5FAC-F2BD1565DA07"; +createNode polySphere -n "polySphere1"; + rename -uid "05DF2B0F-4005-2D8D-2071-0AB0DE93D7BF"; +select -ne :time1; + setAttr ".o" 1; + setAttr ".unw" 1; +select -ne :hardwareRenderingGlobals; + setAttr ".otfna" -type "stringArray" 22 "NURBS Curves" "NURBS Surfaces" "Polygons" "Subdiv Surface" "Particles" "Particle Instance" "Fluids" "Strokes" "Image Planes" "UI" "Lights" "Cameras" "Locators" "Joints" "IK Handles" "Deformers" "Motion Trails" "Components" "Hair Systems" "Follicles" "Misc. UI" "Ornaments" ; + setAttr ".otfva" -type "Int32Array" 22 0 1 1 1 1 1 + 1 1 1 0 0 0 0 0 0 0 0 0 + 0 0 0 0 ; + setAttr ".fprt" yes; +select -ne :renderPartition; + setAttr -s 3 ".st"; +select -ne :renderGlobalsList1; +select -ne :defaultShaderList1; + setAttr -s 5 ".s"; +select -ne :postProcessList1; + setAttr -s 2 ".p"; +select -ne :defaultRenderingList1; +select -ne :lightList1; + setAttr -s 2 ".l"; +select -ne :initialShadingGroup; + setAttr ".ro" yes; +select -ne :initialParticleSE; + setAttr ".ro" yes; +select -ne :defaultRenderGlobals; + setAttr ".ren" -type "string" "arnold"; + setAttr ".outf" 51; + setAttr ".imfkey" -type "string" "exr"; +select -ne :defaultResolution; + setAttr ".pa" 1; +select -ne :defaultLightSet; + setAttr -s 2 ".dsm"; +select -ne :hardwareRenderGlobals; + setAttr ".ctrs" 256; + setAttr ".btrs" 512; +connectAttr "polySphere1.out" "pSphereShape1.i"; +relationship "link" ":lightLinker1" ":initialShadingGroup.message" ":defaultLightSet.message"; +relationship "link" ":lightLinker1" ":initialParticleSE.message" ":defaultLightSet.message"; +relationship "link" ":lightLinker1" "aiStandardVolume1SG.message" ":defaultLightSet.message"; +relationship "link" ":lightLinker1" ":ArnoldStandInDefaultLightSet.message" ":defaultLightSet.message"; +relationship "shadowLink" ":lightLinker1" ":initialShadingGroup.message" ":defaultLightSet.message"; +relationship "shadowLink" ":lightLinker1" ":initialParticleSE.message" ":defaultLightSet.message"; +relationship "shadowLink" ":lightLinker1" "aiStandardVolume1SG.message" ":defaultLightSet.message"; +connectAttr "layerManager.dli[0]" "defaultLayer.id"; +connectAttr "renderLayerManager.rlmi[0]" "defaultRenderLayer.rlid"; +connectAttr ":defaultArnoldDisplayDriver.msg" ":defaultArnoldRenderOptions.drivers" + -na; +connectAttr ":defaultArnoldFilter.msg" ":defaultArnoldRenderOptions.filt"; +connectAttr ":defaultArnoldDriver.msg" ":defaultArnoldRenderOptions.drvr"; +connectAttr "aiStandardVolume1.out" "aiStandardVolume1SG.vs"; +connectAttr "aiVolumeShape.iog" "aiStandardVolume1SG.dsm" -na; +connectAttr "aiStandardVolume1SG.msg" "materialInfo1.sg"; +connectAttr "directionalLightShape2.msg" "hyperShadePrimaryNodeEditorSavedTabsInfo.tgi[0].ni[0].dn" + ; +connectAttr "aiStandardVolume1.msg" "hyperShadePrimaryNodeEditorSavedTabsInfo.tgi[0].ni[1].dn" + ; +connectAttr "aiStandardVolume1SG.msg" "hyperShadePrimaryNodeEditorSavedTabsInfo.tgi[0].ni[2].dn" + ; +connectAttr "aiStandInShape.iog" ":ArnoldStandInDefaultLightSet.dsm" -na; +connectAttr "aiStandardVolume1SG.pa" ":renderPartition.st" -na; +connectAttr "aiStandardVolume1.msg" ":defaultShaderList1.s" -na; +connectAttr "defaultRenderLayer.msg" ":defaultRenderingList1.r" -na; +connectAttr "directionalLightShape1rer.ltd" ":lightList1.l" -na; +connectAttr "directionalLightShape2.ltd" ":lightList1.l" -na; +connectAttr "pSphereShape1.iog" ":initialShadingGroup.dsm" -na; +connectAttr "directionalLight1.iog" ":defaultLightSet.dsm" -na; +connectAttr "directionalLight2.iog" ":defaultLightSet.dsm" -na; +connectAttr "aiStandardVolume1.out" ":internal_standInShader.ic"; +// End of volume.ma diff --git a/tests/volume_render.ass b/tests/volume_render.ass new file mode 100644 index 0000000..a657a79 --- /dev/null +++ b/tests/volume_render.ass @@ -0,0 +1,187 @@ +### exported: Wed Dec 23 20:59:57 2020 +### from: Arnold 5.1.1.1 [3849b993] windows icc-17.0.2 oiio-1.7.17 osl-1.9.0 vdb-4.0.0 clm-1.0.3.513 rlm-12.2.2 2018/06/26 21:12:06 +### host app: MtoA 3.0.1.1 443e943e (master) Maya 2018 +### user: indigo +### render_layer: defaultRenderLayer +### scene: C:/workspace/apShaders/tests/volume.ma + + + +options +{ + AA_samples 3 + AA_samples_max 8 + outputs "RGBA RGBA defaultArnoldFilter@gaussian_filter defaultArnoldDriver@driver_exr.RGBA" + xres 960 + yres 540 + texture_per_file_stats on + texture_searchpath "C:/Users/indigo/Documents/maya/projects/default/sourceimages" + texture_automip off + camera "perspShape" + color_manager "defaultColorMgtGlobals" + frame 1 + procedural_searchpath "C:/Users/indigo/Documents/maya/projects/default/" + GI_diffuse_depth 1 + GI_specular_depth 1 + GI_transmission_depth 8 + declare render_layer constant STRING + render_layer "defaultRenderLayer" +} + +gaussian_filter +{ + name defaultArnoldFilter@gaussian_filter +} + +driver_exr +{ + name defaultArnoldDriver@driver_exr.RGBA + filename "C:/Users/indigo/Documents/maya/projects/default/images/volume.exr" + color_space "" +} + +color_manager_syncolor +{ + name defaultColorMgtGlobals + native_catalog_path "C:/Program Files/Autodesk/Maya2018/synColor" + custom_catalog_path "C:/CGCG/projects/COOKIES/maya/2018/x64/configs/" + rendering_color_space "scene-linear Rec 709/sRGB" +} + +persp_camera +{ + name perspShape + matrix + 0.532876253 -2.77555756e-17 -0.846193194 0 + -0.372782111 0.897732913 -0.234753415 0 + 0.759655416 0.440540195 0.478380561 0 + 865.787048 546.581909 506.338074 1 + near_clip 0.100000001 + far_clip 10000 + screen_window_min -1 -1 + screen_window_max 1 1 + shutter_start 0 + shutter_end 0 + shutter_type "box" + rolling_shutter "off" + rolling_shutter_duration 0 + motion_start 0 + motion_end 0 + exposure 0 + fov 54.4322243 + declare maya_full_name constant STRING + maya_full_name "|persp|perspShape" +} + +distant_light +{ + name directionalLightShape1rer + matrix + -87.9096146 -18.7751865 -279.878418 0 + 84.8637314 277.776001 -45.2897911 0 + 267.362244 -94.3425217 -77.6494827 0 + 0 0 0 1 + exposure 0 + cast_shadows on + cast_volumetric_shadows on + shadow_density 1 + samples 1 + normalize on + diffuse 1 + specular 1 + sss 1 + indirect 1 + max_bounces 999 + volume_samples 2 + volume 1 + aov "default" + angle 0 + declare maya_full_name constant STRING + maya_full_name "|directionalLight1|directionalLightShape1rer" +} + +distant_light +{ + name directionalLightShape2 + matrix + 404.167999 137.387329 -24.2375793 0 + -122.5755 314.238403 -262.762207 0 + -66.6182022 255.330093 336.42691 0 + 0 0 0 1 + exposure 0 + cast_shadows on + cast_volumetric_shadows on + shadow_density 1 + samples 1 + normalize on + diffuse 1 + specular 1 + sss 1 + indirect 1 + max_bounces 999 + volume_samples 2 + volume 1 + aov "default" + angle 0 + declare maya_full_name constant STRING + maya_full_name "|directionalLight2|directionalLightShape2" +} + +procedural +{ + name aiStandInShape + visibility 255 + matrix + 1 0 0 0 + 0 1 0 0 + 0 0 1 0 + 0 0 0 1 + use_light_group off + override_nodes off + filename "C:/workspace/apShaders/tests/volume.ass" + declare maya_full_name constant STRING + maya_full_name "|aiStandIn|aiStandInShape" +} + +polymesh +{ + name pSphereShape1 + visibility 255 + sidedness 255 + matrix + 171.24736 0 0 0 + 0 171.24736 0 0 + 0 0 171.24736 0 + 0 0 -503.261475 1 + shader "lambert1" + use_light_group off + id 2723756714 + nsides 400 1 b85UINT +B!%<_l4$$$%)!$v;Z0$$$$. + vidxs 1560 1 b85UINT +F$Glq$$'GF\$'J8Y$IW1:$Lwac$,R7F$,U)C$Naw$$R-RM$1](0$1_o-$Slgc$W8C7$6gmo$6j_l$XwXM$\C3v$;r^Y$;uPV$^-I7$aN$`$A(OC$A+A@$c89v$fXjJ$$&_A$F61k$hC*`$kc[4$K>0l$K@wi$mMpJ$pnKs$PHvV$PKhS$rXa4$v$<]$USg@$UVY=$wcQs%&/-G$Z^X*$ZaJ'%'nB]%+9s1$_iHi$_l:f%-$3G%0Dcp$dt9S$dw+P%2/$1$h@,s$j**=$j,q:%79ip%:ZED$o4p'$o7b$%j%8uiM%8x[J%[0T+%^Q/T%>+Z7%>.L4%`;Dj%c[u>%C6Jv%C9%mqVg%ML,J%MNsG%o[l(%s'GQ%RVr4%RYd1%tf\g%x28;%5U-2%WdT\&$qMQ&(=)%%\lS]%\oEZ&*'>;&-Gnd%awDG%b%6D&/2/%&2R_N%g-51%g0'.&4RV8&As1a%vM\D%vPNA&C]Fw&$nOd&&XM.&&[?+&Hh7a&L3h5&+c=m&+f/j&Ms(K&Q>Xt&0n.W&0puT&S(n5&VII^&5xtA&6&f>&X3^t&[T:H&;.e+&;1W(&]>O^&`_+2&@9Uj&@x&jta[&JO7>&JR);&l^vq&p*RE&OZ((&O\o%&qig[&u5C/&Tdmg&Tg_d&vtXE'%@3n&Yo^Q&YrPN''*I/'*K$X&_%O;&_(A8',59n'/UjB&d0@%&d31w'1@*X'4`[,&G.Ox&i=wM'6JpB'9kKk&nEvN&nHhK';Ua,'>vb'VriE'Vu[B($*ai('N/L'\(Z/'\+L,()8Db(,Xu6'a3Jn'a6;X'fA-U(3N&6(6nV_'kI,B'kKs?(8Xku(<$GI'pSr,'pVd)(=c\_(A/83'u^bk'uaTh(BnMI(F:(r'X\ri(%lE>(H$>3(KDn\(*tD?(*w6<(M/.r(PO_F(0*5)(0-'&(R9t\(UZP0(55%h(57le(WDeF(Ze@o(:?kR(:B]O(\OV0(_p1Y(?J\<(?MN9(aZFo(e%wC(DUM&(DX>x(fe7Y(Gv@F(I`=e(Ic/b(kp(C(o;Xl(Nk.O(NmuL(q%n-(tFIV(Sut9(Sxf6(v0^l)$Q:@(Y+dx(Y.Vu)&;OV))\+*(^6Ub(^9G_)+F@@).fpi(cAFL(cD8I)0Q1*)3qaS(hL76(hO)3)5Y/Z)9'R=(mW'u(mYnr):fgS)>2C'(ram_(rd_\)?qX=)C=3f(wl^I(woPF)E'I')HH$P)'wO3)(%A0)J29f)MRj:)--?r)-01o)O=*P)R][$)280\)2:wY)TGp:)WhKc(j6@Z)7Eh/)YRa$)\sc`)Kn9C)Kq+@)n(xv)qITJ)Q$*-)Q&q*)s3i`)vTE4)V.ol)V1ai)x>ZJ)YOc7)[9`V)[Z)toi=)tr[:*B*Sp*EK/D*%%Z'*%(L$*G2RK*JUu.**0Jf**3-M*QK&.*TkVW*4F,:*4Hs7*VUkm*YvGA*9Pr$*9Scv*[`\W*_,8+*>[bc*>^T`*`kMA*d7(j*CfSM*CiEJ*ev>+*iAnT*&dcK*Ht5u*k,.j*nL_>*N'4v*N*&s*p6tT*sWP(*S2%`*S4l]*uAe>*xb@g*Xp+/b7Q+3-h%*g]=]*g`/Z+4m(;*k)1(*lh.G*ljuD+9wn%+=CIN*qrt1*quf.+?-^d+BN:8*w(dp*w+Vm+D8ON+GY*w+'3UZ+'6GW+IC@8+Lcpa+,>FD+,A8A+NN0w+QnaK+1I7.+1L)++SXva+W$R5+6T'm+6Vnj+X`u<+Yj%R+Yj1W+Yj=\+YjIa+YjUf+Yjak+Yjmp+Yk$u+Yk1%+Yk=*+YkI/+YkU4+Yka9+Ykm>+Yl$C+Yl0H+Yl$GoW-$IVb>$IVnF$K>Tg$R08V$SlCg$SlOo$UT6;$\Eo*$^-%;$^-1C$_ild$f[PS$$)E7$)3rI$j*)Y$ka82$/uZ&$0%nh$mMp;$plM,$:6;M$:;,-$rXa($uwb%$DKqs$DP>G$wcQj%&-vs$NaSD$NePa%'nBW%+96l$Xw4j$Y%c&%-$3D%0DKe$c7k;$c:u@%2/$1$j$j?$hC+1$hEr-%5R^`%:ZED$o4p'$o7b$%+Z7%>.L4%`;Dj%c[u>%C6Jv%C9%mqVg%ML,J%MNsG%o[l(%s'GQ%RVr4%RYd1%tf\g%x28;%7<8B%YK_m&&XL\&(=)$%\lS\%\oEZ&*'>;&-Gnd%awDG%b%6D&/2/%&2R_N%g-51%g0'.&4RV8&As1a%vM\D%vPNA&C]Fw&&Ufx&$qMw&$t?s&G,,Q&L3h5&+c=m&+f/j&Ms(K&Q>Xt&0n.W&0puT&S(n5&VII^&5xtA&6&f>&X3^t&[T:H&;.e+&;1W(&]>O^&`_+2&@9Uj&@vb'VriE'Vu[B($*mn(%fm9'\(N,'\+@(()8Db(,Xu6'a3Jn'a6;X'fA-U(3N&6(6nV_'kI,B'kKs?(8Xku(<$GI'pSr,'pVd)(=c\_(A/83'u^bk'uaTh(BnMI(F:(r'ZD)$('SPO(I`=>(KDn[(*tD>(*w6<(M/.r(PO_F(0*5)(0-'&(R9t\(UZP0(55%h(57le(WDeF(Ze@o(:?kR(:B]O(\OV0(_p1Y(?J\<(?MN9(aZFo(e%wC(DUM&(DX>x(fe7Y(I]WZ(H$>Y(H'0U(j3r3(o;Xl(Nk.O(NmuL(q%n-(tFIV(Sut9(Sxf6(v0^l)$Q:@(Y+dx(Y.Vu)&;OV))\+*(^6Ub(^9G_)+F@@).fpi(cAFL(cD8I)0Q1*)3qaS(hL76(hO)3)5Y;_)7@;*(mVpr(mYbn):fgS)>2C'(ram_(rd_\)?qX=)C=3f(wl^I(woPF)E'I')HH$P)'wO3)(%A0)J29f)MRj:)--?r)-01o)O=*P)R][$)280\)2:wY)TGp:)WhKc(krKj)9,s@)[9`/)\sc`)Kn9C)Kq+@)n(xv)qITJ)Q$*-)Q&q*)s3i`)vTE4)V.ol)V1ai)x>ZJ)[7%K)YRaJ)YUSF*&b@$*+j&])`DQ@)`GC=*-T;s*0tlG)eOB*)eR4'*2_,]*6*]1)jZ2i)j]$f*7irG*;5Mp)odxS)ogjP*Z)toi=)tr[:*B*Sp*EK/D*%%Z'*%(L$*G2^P*Hn]p**0>c**30_*L@5D*O`em*/;;P*/>-M*QK&.*TkVW*4F,:*4Hs7*VUkm*YvGA*9Pr$*9Scv*[`\W*_,8+*>[bc*>^T`*`kMA*d7(j*CfSM*CiEJ*ev>+*iAnT*(Kn[*J[A1*lh-u*nL_=*N'4u*N*&s*p6tT*sWP(*S2%`*S4l]*uAe>*xb@g*Xp+/b7Q+3-h%*g]=]*g`/Z+4m(;*leH<*k,/;*k.v7+8;bj+=CIN*qrt1*quf.+?-^d+BN:8*w(dp*w+Vm+D8ON+GY*w+'3UZ+'6GW+IC@8+Lcpa+,>FD+,A8A+NN0w+QnaK+1I7.+1L)++SXva+W$R5+6T'm+6Vnj+Xa,A+Yj%R+Yj1Y+YjUg+Yjmq+Yk1&+YkI0+Yka:+Yl$D+YlHN$N^ls$,R7G$,U5H$PI98$Si]]$1](1$1`&2$UT)w$XtNG$6gmp$6jkq$Z^oa$^*?1$;r^Z$;u\[$_i`K$c5/p$A(OD$A+ME$dtQ5$h?uZ$F3@.$GrI?$kfY4$o2(Y$M%H-$M(F.$pqIs$t'W%&2+G%)ROl$\Eo@$\HmA%++Z8%>.X9%aw\)%eC+N%C6Jw%C9Hx%g-Lh%jMq8%HA;a%HD9b%l8=R%oXaw%ML,K%MO*L%qC.<%tcRa%RVr5%RYp6%vMt&&$nCK%Wabt%Wd`u&&Xde&*$45%\lS^%^V\o&-Jld&0k<4%c^[]%caY^&2U]N&5v,s%hiLG%hlJH&7`N8&;+r]%mt=1%mw;2&w&@6cG%s*-p%s-+q&Av/a&EAT1%x4sZ%x7q[&G+uK&JLDp&(?dD&(BbE&L6f5&OW5Z&/1lB&/4jD&S(n4&VI=Y&4<]-&4?[.&X3^s&[T.C&9GMl&9JKm&]>O]&`^t-&>R>V&>U''3'Al'6Gf<&i;0e&i>.f'822V';RW&&nEvO&nHtP'=xwt'?&uu'bp$e'f;I5'Ek*r'En(t'ib,d'm-Q4'Jup]'Jxn^'nlrN'r8As'P+aG'P._H'swc8'wC2]'U6R1'U9P2($-Sw('MxG'ZABp'ZD@q()8Da(,Xi1'_L3Z'_O1[(.C5K(1cYp'dW$D'dYwE(3N&5(8Uao'kI,C'kL*D(:@.4(=`RY'pSr-'pVp.(?Jss(BkCC'u^bl'ua`m(DUd](Gv4-(%iSV(%lQW(I`UG(M,$l(*tD@(*wBA(NkF1(R6jV(0*5*(0-3+(Sv6p(WA[@(55%i(6t/%(Zh>o(^3c?(<'-h(<*+i(_s/Y(c>T)(A1sR(A4qS(e(uC(hIDh(FVl(r_&<(PREe(PUCf(tIGV(wil&(U]6O(U`4P)$T8@)'t\e(\O>M(\R26w(q%VK(q(TL)?qX<)C='a(v0G5(v3E6)E'I&)HGmK)&;7t)&>5u)J29e)O9uJ)--?s)-0=t)Q$Ad)TDf4)280])2;.^)V/2N)YOVs)7BvG)7EtH)[9x8)^ZG])Xp@)s3R()s6P**B*So*EJx?)x>Bh)xA@i*G5DY*JUi)*(I3R*(L1S*L@5C*O`Yh*-T$<*-Vw=*QK&-*TkJR*2^j&*2ah'*VUkl*Yv;<*7iZe*7lXf*[`\V*_,,&*[8*S2%a*S4xb*w)'R+%IKw*X^&+/_-K*bRLt*d1+.%]Z+.([[+Qq_K+U=.p+4leX+4ocZ+XcgJ+\/6o+9wVC+:%TD+]nX4+a:'Y+?-G-+?0E.+c$Hs+fDmC+D87l+D;5m+h/9]+kO^-+IC(V+IF&W+m:*G+pZNl+NMn@+NPlA+rDp1+ue?V+SX_*+S[]++wO`p,%:P.,&vgC,(^)X,*E@m,,,X-,-hoB,/P1W,17Hl,2s`,,4ZwA,6B9V,8)Pk,9eh+,;M*@,=4AU,>pXj,@Wp*,B?2?,D&IT,Eb`i,H'r1,Id4F,KKK[,M2bp,No%0,PVaQ7[Aa/f5)7xuYSaQ7[Aa794h7l?EtaQ7[Aa9['fzaQ7[Aa:L<8`x/vJaQ7[Aa9['ea/f5'aQ7[Aa794fa794faQ7[Aa/f5&a9['caQ7[A`x/vGa:L<5aQ7[Aza9['caQ7[A7l?Eqa794eaQ7[A7xuYOa/f5%aQ7[A8+HY:`x/vGaQ7[A8-jL7]8wuQaQ7[A8.[`^7l?EmaQ7[A8-jL67xuYLaQ7[A8+HY98+HY8aQ7[A7xuYM8-jL6aQ7[A7l?En8.[`]aQ7[Az85BheaOV5ba+:2Y81k?taOV5ba82J)8,AnSaOV5ba=[pI7tIW-aOV5baA3D9zaOV5baBETaa+:2XaOV5baA3D8a82J'aOV5ba=[pFa=[pEaOV5ba82J&aA3D6aOV5ba+:2UaBET^aOV5bzaA3D6aOV5b7tIW*a=[pDaOV5b8,AnOa82J%aOV5b81k?na+:2UaOV5b85Bh^]@q8xaOV5b86U$17tIW(aOV5b85Bh]8,AnMaOV5b81k?m81k?laOV5b8,AnN85Bh\aOV5b7tIW)86U$/aOV5bz8:_aQaMAiaa/f5)87d&JaMAiaa,;a/f5(aMAiaaFP=%a,8aMAiazaFPcW<8'x-gaJT2f8=h8A84LjgaJT2f8;)%18;)%1aJT2f84Lji8=h8@aJT2f8'x-i8>cW;aJT2fz8@J=naG>,6a794h8=>KTaG>,6aCTVt87d&IaG>,6aI/')8+HY,6aL:nBzaG>,6aMAiga794gaG>,6aL:nAaCTVqaG>,6aI/''aI/'&aG>,6aCTVoaL:n?aG>,6a794eaMAidaG>,6zaL:n?aG>,68+HY:aI/'%aG>,687d&CaCTVnaG>,68=>KNa794eaG>,68@J=g]KmN*aG>,68AQ988+HY7aG>,68@J=g87d&@aG>,68=>KM8=>KMaG>,687d&A8@J=faG>,68+HY88AQ96aG>,6z8BUCkaBETZa8YmK8?.MqaBETZaES@889bdbaBETZaJt)F8,iza-&.3aR7`ga::XDa-&.3aPqK=aG-,<8;MPfzaMAii8.[`bzaQ7[IzzaRT=ha:L<8zaQ7[HaG>,:zaMAifaMAiezaG>,9aQ7[Eza:L<5aRT=fzzaQ7[Ez8.[`_aMAidz8;MPbaG>,8z8AQ98a:L<5z8EG*m]Q*w-z8Fcb:8.[`\z8EG*l8;MP`z8AQ978AQ96z8;MPa8EG*kz8.[`]yzz8E+oj7v5R]a::XE8A:.B7v5R]aG-z7v5R]aR7`ga::XD7v5R]aPqK=aG-KT8;MP`aCTVt87d&I8;MP`aI/')8+HY<8;MP`aL:nBz8;MP`aMAiga794g8;MP`aL:nAaCTVq8;MP`aI/''aI/'&8;MP`aCTVoaL:n?8;MP`a794eaMAid8;MP`zaL:n?8;MP`8+HY:aI/'%8;MP`87d&CaCTVn8;MP`8=>KNa794e8;MP`8@J=g]KmN*8;MP`8AQ988+HY78;MP`8@J=g87d&@8;MP`8=>KM8=>KM8;MP`87d&A8@J=f8;MP`8+HY88AQ968;MP`z8=h8G8>cW;a3h^G8;)%78>cW;a@=FF84Ljp8>cW;aFnUa8'x-p8>cW;aIXhqz8>cW;aJT2la3h^F8>cW;aIXhpa@=FC8>cW;aFnU_aFnU^8>cW;a@=FBaIXhn8>cW;a3h^AaJT2i8>cW;zaIXhn8>cW;8'x-kaFnU^8>cW;84Ljja@=F@8>cW;8;)%2a3h^A8>cW;8=h8A]I*l/8>cW;8>cW<8'x-g8>cW;8=h8A84Ljg8>cW;8;)%18;)%18>cW;84Lji8=h8@8>cW;8'x-i8>cW;8>cW;z8:_aQ8AQ96a/f5)87d&J8AQ96a,;a/f5(8AQ96aFP=%a,88AQ96zaFP8EG*ka/f5)7xuYS8EG*ka794h7l?Et8EG*ka9['fz8EG*ka:L<8`x/vJ8EG*ka9['ea/f5'8EG*ka794fa794f8EG*ka/f5&a9['c8EG*k`x/vGa:L<58EG*kza9['c8EG*k7l?Eqa794e8EG*k7xuYOa/f5%8EG*k8+HY:`x/vG8EG*k8-jL7]8wuQ8EG*k8.[`^7l?Em8EG*k8-jL67xuYL8EG*k8+HY98+HY88EG*k7xuYM8-jL68EG*k7l?En8.[`]8EG*kz7uCHt8FG04`jc&P7rt'w8FG04`wC3.7kRWX8FG04a)dXM7^rJx8FG04a,4$Iz8FG04a-&.?`jc&N8FG04a,4$H`wC3,8FG04a)dXKa)dXJ8FG04`wC3*a,4$F8FG04`jc&Ka-&.=8FG04za,4$F8FG047^rJua)dXJ8FG047kRWS`wC3)8FG047rt's`jc&K8FG047uCHo]+QgX8FG047v5Re7^rJq8FG047uCHn7kRWQ8FG047rt'r7rt'r8FG047kRWR7uCHn8FG047^rJr7v5Rd8FG04zzaRT=dzzyz + nlist 382 1 b85VECTOR +8$sL?aR%6>`p]C(7vj/8aR%6>a($j&8,Oq4aQ$=Ea1Ba1j/2]ZEXpaQ$=Ea;iAh`p]BBaR%6?a0d'ta$guxaQ$=Da:rPna($inaR%6>a-Z`,a1B7dlgqa:rPoaQ$=C7mwEMa-Z_iaR%6?7q49%a8@LcaQ$=C8%Qa:a($iiaR%6@7vj/6a1B7dlgx8/,uEaQ$=A7mwE_8&$SXaR%6@5(Kln8/xfEaQ$=D4n,BY82U=faOAqMa8`53867kIaOAqLa+j;W8,oYWaOAqMa>En;7u$`;aOAqNaB(Fp]^u6:aOAqMaC>G8a+j;saOAqNaB(Fta8`55aOAqLa>En?a>En@aOAqMa8`51aB(FxaOAqMa+j;haC>G@aOAqK4Y^O1aB(G%aOAqK7u$`Fa>EnAaOAqK8,oY]a8`50aOAqL82U=ma+j;kaOAqJ867kP4J,])aOAqJ87Mkl7u$`FaOAqK867kM8,oY\aOAqK82U=k82U=jaOAqJ8,oYb867kOaOAqL7u$`@87MkgaOAqM4i*v)88;[taM-K^a%E_aJ@lva4+;Q84c;FaJ@luaG)&O8(:`VaJ@lsaIjv2]_U%E^]2IK3aJ@lr8>v_'8(:`caJ@lt8>%E]84c;QaJ@lq8;8K%8;8K$aJ@lq84c;K8>%E\aJ@lq8(:`W8>v_'aJ@lq5/=Vk8=HJ&aG,t^aCc,n8@V'DaG,t\a7@i]87rQ>aG,t]aI9%T8+P9HaG,t[aLFWk]hcZA7aG,tY8A]V-8+P9PaG,tY8@V'>87rQFaG,tY8=HJ'8=HJ)aG,tY87rQC8@V'@aG,tY8+P9K8A]V.aG,tY50&a>8?43^aB)a>aEWKc8B\)XaB)a?a8^5`89fp4aB)a@aK$d78,mZJaB)aDaNLZ)]Yd;iaB)aDaO]8ja8^6,aB)aDaNLZ'aEWKeaB)aCaK$d1aK$d5aB)aAaEWK_aNLZ(aB)aBa8^6$aO]8jaB)aG]SCosaNLZ'aB)aF8,mZOaK$d3aB)aD89fp8aEWKaaB)a@8?43_a8^6&aB)a>8B\)S4]4BYaB)a;8Cl]?8,mZTaB)a<8B\)S89fp6aB)a;8?43^8?43`aB)a<89fp78B\)TaB)a>8,mZP8Cl]AaB)a<52v)T8@LmMa:8ZwaFR128D3$9a:8Zwa9\x^8:aUXa:8[$aL=I&8-lHLa:8[&aOxT_]2EE>a:8[$aQ:iJa9]$-a:8ZxaOxT^aFR14a:8[%aL=HvaL=I&a:8[$aFR1/aOxT_a:8Zwa9]$&aQ:iJa:8[']Db/faOxT]a:8[&8-lHRaL=I$a:8Zp8:aU\aFR10a:8Zq8@LmPa9]$$a:8Zu8D3$44e9woa:8Zv8EJ8t8-lHUa:8Zx8D3$38:aU[a:8Zw8@LmN8@LmOa:8Zv8:aU[8D3$4a:8Zt8-lHP8EJ8wa:8Zq53XsU8A:e0a,fiLaG-dd8E,[,68EG*p\jrsaa:L;i8;MP]]I`mKaMAib8.[`S]I`mMaQ7[BzzaRT=da:L<;]I`mPaQ7[@aG>,:]H,4aQ7[A3_-C8a:L<2aRT=c\jrsa3leGaaQ7[?\xUx78.[`_aMAi_z8;MPbaG>,5]FmUA8AQ98a:L<.]LT0e8EG*kzz8Fcb88.[`^\jrsc8EG*k8;MPa\xUx<8AQ978AQ96\jrsc8;MP`8EG*kz8.[`_y3_-C453fkZ8A:e07uv8uaG-dd8E,[<7uv9&a:;,o8;=457uv9(aM+@]8.JQ\7uv9(aPr6cz7uv9$aR8OQa:;-?7uv9%aPr6`aG-dg7uv8waM+@WaM+@\7uv8taG-d`aPr6d7uv8ma:;-6aR8OR7uv8b4%`)+aPr6b7uv8a8.JQcaM+@Z7uv8j8;=49aG-db7uv8t8A:e0a:;-47uv8x8E,[74W=-`7uv9$8FGt&8.JQe7uv9$8E,[68;=487uv8v8A:e/8A:e07uv8w8;=488E,[97uv8t8.JQc8FGt&7uv8x53Dx68@LmM8.H*NaFR138D3$98.H*Na9\x^8:aUX8.H*OaL=I'8-lHL8.H*PaOxT_]2EE>8.H*OaQ:iJa9]$,8.H*NaOxT\aFR138.H*MaL=HvaL=I'8.H*MaFR1/aOxT_8.H*La9]$&aQ:iJ8.H*N]:)QhaOxT_8.H*L8-lHRaL=I$8.H*G8:aU\aFR108.H*F8@LmQa9]$$8.H*J8D3$44eYgJ8.H*K8EJ8t8-lHS8.H*M8D3$28:aU[8.H*M8@LmO8@LmO8.H*K8:aU[8D3$48.H*H8-lHP8EJ8w8.H*I52v;@8?43]8690laEWKc8B\)Y8690ka8^5`89fp48690laK$d68,mZL8690naNLZ*]Yd;i8690naO]8ja8^6+8690oaNLZ'aEWKe8690kaK$d1aK$d68690kaEWK_aNLZ*8690ma8^6&aO]8j8690m]OP%E^8>PPPPPPPPPPPPP%E^]2IK38>Pv_'8(:`c8>P%E]84c;N8>PP%E\8>Pv_(8>PEnF7u$`98CQ@vaB(Fs]`=mC8CQ@xaC>G6a+j;s8CQ@xaB(Foa8`548CQ@wa>En:a>En@8CQ@va8`5-aB(G$8CQ@wa+j;naC>G@8CQ@u4Y^O1aB(Fx8CQ@u7u$`Ua>En@8CQ@v8,oY]a8`518CQ@w82U=ia+j;l8CQ@t867kQ4I`qe8CQ@t87Mkp7u$`H8CQ@u867kP8,oY]8CQ@v82U=k82U=l8CQ@u8,oY`867kL8CQ@t7u$`F87Mkg8CQ@w4piDe8,Oq38E3ama1B=/8/,uC8E3ana$guO8%QaB8E3ala8@Lj7mwE<8E3aoa:rPi]ZEXp8E3aoa;iAaa$guw8E3aoa:rPfa1B0s7_[,H7uNfZ7_[,H8%v5I7_[,H8+HY87_[,H8.1k07_[,H80p((7_[,H83Y9u7_[,H86BKm7_[,H89+]d7_[,H8:Jf`7_[,H8;io\7_[,H8=3xX7_[,H8>S,T7_[,H8?r5P7_[,H8A<>L7_[,H8B[GH7_[,H8D%PD7_[,H8EDY@7_[,H8Fcb:7_[,Hz7m>0s7_[,H!7m>0s$$$$'7uNfZ7m>0s8%v5I7m>0s8+HY87m>0s8.1k07m>0s80p((7m>0s83Y9u7m>0s86BKm7m>0s89+]d7m>0s8:Jf`7m>0s8;io\7m>0s8=3xX7m>0s8>S,T7m>0s8?r5P7m>0s8A<>L7m>0s8B[GH7m>0s8D%PD7m>0s8EDY@7m>0s8Fcb:7m>0sz7uNfZ7_[,H7uNfZ7m>0s!7uNfZ$$$$'8%v5I7uNfZ8+HY87uNfZ8.1k07uNfZ80p((7uNfZ83Y9u7uNfZ86BKm7uNfZ89+]d7uNfZ8:Jf`7uNfZ8;io\7uNfZ8=3xX7uNfZ8>S,T7uNfZ8?r5P7uNfZ8A<>L7uNfZ8B[GH7uNfZ8D%PD7uNfZ8EDY@7uNfZ8Fcb:7uNfZz8%v5I7_[,H8%v5I7m>0s8%v5I7uNfZ!8%v5I$$$$'8+HY88%v5I8.1k08%v5I80p((8%v5I83Y9u8%v5I86BKm8%v5I89+]d8%v5I8:Jf`8%v5I8;io\8%v5I8=3xX8%v5I8>S,T8%v5I8?r5P8%v5I8A<>L8%v5I8B[GH8%v5I8D%PD8%v5I8EDY@8%v5I8Fcb:8%v5Iz8+HY87_[,H8+HY87m>0s8+HY87uNfZ8+HY88%v5I!8+HY8$$$$'8.1k08+HY880p((8+HY883Y9u8+HY886BKm8+HY889+]d8+HY88:Jf`8+HY88;io\8+HY88=3xX8+HY88>S,T8+HY88?r5P8+HY88A<>L8+HY88B[GH8+HY88D%PD8+HY88EDY@8+HY88Fcb:8+HY8z8.1k07_[,H8.1k07m>0s8.1k07uNfZ8.1k08%v5I8.1k08+HY8!8.1k0$$$$'80p((8.1k083Y9u8.1k086BKm8.1k089+]d8.1k08:Jf`8.1k08;io\8.1k08=3xX8.1k08>S,T8.1k08?r5P8.1k08A<>L8.1k08B[GH8.1k08D%PD8.1k08EDY@8.1k08Fcb:8.1k0z80p((7_[,H80p((7m>0s80p((7uNfZ80p((8%v5I80p((8+HY880p((8.1k0!80p(($$$$'83Y9u80p((86BKm80p((89+]d80p((8:Jf`80p((8;io\80p((8=3xX80p((8>S,T80p((8?r5P80p((8A<>L80p((8B[GH80p((8D%PD80p((8EDY@80p((8Fcb:80p((z83Y9u7_[,H83Y9u7m>0s83Y9u7uNfZ83Y9u8%v5I83Y9u8+HY883Y9u8.1k083Y9u80p((83Y9u83Y9u83Y9u86BKm83Y9u89+]d83Y9u8:Jf`83Y9u8;io\83Y9u8=3xX83Y9u8>S,T83Y9u8?r5P83Y9u8A<>L83Y9u8B[GH83Y9u8D%PD83Y9u8EDY@83Y9u8Fcb:83Y9uz86BKm7_[,H86BKm7m>0s86BKm7uNfZ86BKm8%v5I86BKm8+HY886BKm8.1k086BKm80p((86BKm83Y9u!86BKm$$$$'89+]d86BKm8:Jf`86BKm8;io\86BKm8=3xX86BKm8>S,T86BKm8?r5P86BKm8A<>L86BKm8B[GH86BKm8D%PD86BKm8EDY@86BKm8Fcb:86BKmz89+]d7_[,H89+]d7m>0s89+]d7uNfZ89+]d8%v5I89+]d8+HY889+]d8.1k089+]d80p((89+]d83Y9u89+]d86BKm!89+]d$$$$'8:Jf`89+]d8;io\89+]d8=3xX89+]d8>S,T89+]d8?r5P89+]d8A<>L89+]d8B[GH89+]d8D%PD89+]d8EDY@89+]d8Fcb:89+]dz8:Jf`7_[,H8:Jf`7m>0s8:Jf`7uNfZ8:Jf`8%v5I8:Jf`8+HY88:Jf`8.1k08:Jf`80p((8:Jf`83Y9u8:Jf`86BKm8:Jf`89+]d!8:Jf`$$$$'8;io\8:Jf`8=3xX8:Jf`8>S,T8:Jf`8?r5P8:Jf`8A<>L8:Jf`8B[GH8:Jf`8D%PD8:Jf`8EDY@8:Jf`8Fcb:8:Jf`z8;io\7_[,H8;io\7m>0s8;io\7uNfZ8;io\8%v5I8;io\8+HY88;io\8.1k08;io\80p((8;io\83Y9u8;io\86BKm8;io\89+]d8;io\8:Jf`!8;io\$$$$'8=3xX8;io\8>S,T8;io\8?r5P8;io\8A<>L8;io\8B[GH8;io\8D%PD8;io\8EDY@8;io\8Fcb:8;io\z8=3xX7_[,H8=3xX7m>0s8=3xX7uNfZ8=3xX8%v5I8=3xX8+HY88=3xX8.1k08=3xX80p((8=3xX83Y9u8=3xX86BKm8=3xX89+]d8=3xX8:Jf`8=3xX8;io\!8=3xX$$$$'8>S,T8=3xX8?r5P8=3xX8A<>L8=3xX8B[GH8=3xX8D%PD8=3xX8EDY@8=3xX8Fcb:8=3xXz8>S,T7_[,H8>S,T7m>0s8>S,T7uNfZ8>S,T8%v5I8>S,T8+HY88>S,T8.1k08>S,T80p((8>S,T83Y9u8>S,T86BKm8>S,T89+]d8>S,T8:Jf`8>S,T8;io\8>S,T8=3xX!8>S,T$$$$'8?r5P8>S,T8A<>L8>S,T8B[GH8>S,T8D%PD8>S,T8EDY@8>S,T8Fcb:8>S,Tz8?r5P7_[,H8?r5P7m>0s8?r5P7uNfZ8?r5P8%v5I8?r5P8+HY88?r5P8.1k08?r5P80p((8?r5P83Y9u8?r5P86BKm8?r5P89+]d8?r5P8:Jf`8?r5P8;io\8?r5P8=3xX8?r5P8>S,T!8?r5P$$$$'8A<>L8?r5P8B[GH8?r5P8D%PD8?r5P8EDY@8?r5P8Fcb:8?r5Pz8A<>L7_[,H8A<>L7m>0s8A<>L7uNfZ8A<>L8%v5I8A<>L8+HY88A<>L8.1k08A<>L80p((8A<>L83Y9u8A<>L86BKm8A<>L89+]d8A<>L8:Jf`8A<>L8;io\8A<>L8=3xX8A<>L8>S,T8A<>L8?r5P!8A<>L$$$$'8B[GH8A<>L8D%PD8A<>L8EDY@8A<>L8Fcb:8A<>Lz8B[GH7_[,H8B[GH7m>0s8B[GH7uNfZ8B[GH8%v5I8B[GH8+HY88B[GH8.1k08B[GH80p((8B[GH83Y9u8B[GH86BKm8B[GH89+]d8B[GH8:Jf`8B[GH8;io\8B[GH8=3xX8B[GH8>S,T8B[GH8?r5P8B[GH8A<>L!8B[GH$$$$'8D%PD8B[GH8EDY@8B[GH8Fcb:8B[GHz8D%PD7_[,H8D%PD7m>0s8D%PD7uNfZ8D%PD8%v5I8D%PD8+HY88D%PD8.1k08D%PD80p((8D%PD83Y9u8D%PD86BKm8D%PD89+]d8D%PD8:Jf`8D%PD8;io\8D%PD8=3xX8D%PD8>S,T8D%PD8?r5P8D%PD8A<>L8D%PD8B[GH!8D%PD$$$$'8EDY@8D%PD8Fcb:8D%PDz8EDY@7_[,H8EDY@7m>0s8EDY@7uNfZ8EDY@8%v5I8EDY@8+HY88EDY@8.1k08EDY@80p((8EDY@83Y9u8EDY@86BKm8EDY@89+]d8EDY@8:Jf`8EDY@8;io\8EDY@8=3xX8EDY@8>S,T8EDY@8?r5P8EDY@8A<>L8EDY@8B[GH8EDY@8D%PD!8EDY@$$$$'8Fcb:8EDY@7Qx'rz7gkb/z7reTbz7x7xRz8(_GAz8,gb4z8/Pt,z82:0xz84xBpz87aThz89eb6z8;/k2z8