Merged changes in the trunk up to revision 53584.
Conflicts resolved: release/scripts/startup/bl_ui/properties_render.py source/blender/blenloader/intern/readfile.c source/blender/editors/interface/interface_templates.c source/blender/makesrna/RNA_enum_types.h Also made additional code updates for: r53355 UIList - Python-extendable list of UI items r53460 Alpha premul pipeline cleanup
This commit is contained in:
@@ -129,6 +129,8 @@ option(WITH_IK_ITASC "Enable ITASC IK solver (only disable for development
|
|||||||
option(WITH_IK_SOLVER "Enable Legacy IK solver (only disable for development)" ON)
|
option(WITH_IK_SOLVER "Enable Legacy IK solver (only disable for development)" ON)
|
||||||
option(WITH_FFTW3 "Enable FFTW3 support (Used for smoke and audio effects)" ON)
|
option(WITH_FFTW3 "Enable FFTW3 support (Used for smoke and audio effects)" ON)
|
||||||
option(WITH_BULLET "Enable Bullet (Physics Engine)" ON)
|
option(WITH_BULLET "Enable Bullet (Physics Engine)" ON)
|
||||||
|
option(WITH_SYSTEM_BULLET "Use the systems bullet library (currently unsupported due to missing features in upstream!)" )
|
||||||
|
mark_as_advanced(WITH_SYSTEM_BULLET)
|
||||||
option(WITH_GAMEENGINE "Enable Game Engine" ON)
|
option(WITH_GAMEENGINE "Enable Game Engine" ON)
|
||||||
option(WITH_PLAYER "Build Player" OFF)
|
option(WITH_PLAYER "Build Player" OFF)
|
||||||
option(WITH_OPENCOLORIO "Enable OpenColorIO color management" ON)
|
option(WITH_OPENCOLORIO "Enable OpenColorIO color management" ON)
|
||||||
@@ -149,6 +151,9 @@ mark_as_advanced(WITH_HEADLESS)
|
|||||||
option(WITH_AUDASPACE "Build with blenders audio library (only disable if you know what you're doing!)" ON)
|
option(WITH_AUDASPACE "Build with blenders audio library (only disable if you know what you're doing!)" ON)
|
||||||
mark_as_advanced(WITH_AUDASPACE)
|
mark_as_advanced(WITH_AUDASPACE)
|
||||||
|
|
||||||
|
option(WITH_BOOL_COMPAT "Continue defining \"TRUE\" and \"FALSE\" until these can be replaced with \"true\" and \"false\" from stdbool.h" ON)
|
||||||
|
mark_as_advanced(WITH_BOOL_COMPAT)
|
||||||
|
|
||||||
|
|
||||||
# (unix defaults to OpenMP On)
|
# (unix defaults to OpenMP On)
|
||||||
if((UNIX AND NOT APPLE) OR (MINGW))
|
if((UNIX AND NOT APPLE) OR (MINGW))
|
||||||
@@ -267,7 +272,6 @@ mark_as_advanced(WITH_CXX_GUARDEDALLOC)
|
|||||||
option(WITH_ASSERT_ABORT "Call abort() when raising an assertion through BLI_assert()" OFF)
|
option(WITH_ASSERT_ABORT "Call abort() when raising an assertion through BLI_assert()" OFF)
|
||||||
mark_as_advanced(WITH_ASSERT_ABORT)
|
mark_as_advanced(WITH_ASSERT_ABORT)
|
||||||
|
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
cmake_minimum_required(VERSION 2.8.8)
|
cmake_minimum_required(VERSION 2.8.8)
|
||||||
cmake_policy(VERSION 2.8.8)
|
cmake_policy(VERSION 2.8.8)
|
||||||
@@ -426,6 +430,13 @@ endif()
|
|||||||
|
|
||||||
TEST_SSE_SUPPORT(COMPILER_SSE_FLAG COMPILER_SSE2_FLAG)
|
TEST_SSE_SUPPORT(COMPILER_SSE_FLAG COMPILER_SSE2_FLAG)
|
||||||
|
|
||||||
|
TEST_STDBOOL_SUPPORT()
|
||||||
|
if(HAVE_STDBOOL_H)
|
||||||
|
add_definitions(-DHAVE_STDBOOL_H)
|
||||||
|
endif()
|
||||||
|
if(WITH_BOOL_COMPAT)
|
||||||
|
add_definitions(-DWITH_BOOL_COMPAT)
|
||||||
|
endif()
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
# Check for valid directories
|
# Check for valid directories
|
||||||
@@ -1090,14 +1101,16 @@ elseif(WIN32)
|
|||||||
if(WITH_PYTHON)
|
if(WITH_PYTHON)
|
||||||
# normally cached but not since we include them with blender
|
# normally cached but not since we include them with blender
|
||||||
if(MSVC10)
|
if(MSVC10)
|
||||||
set(PYTHON_VERSION 3.2) # CACHE STRING)
|
set(PYTHON_VERSION 3.3) # CACHE STRING)
|
||||||
else()
|
else()
|
||||||
set(PYTHON_VERSION 3.3) # CACHE STRING)
|
set(PYTHON_VERSION 3.3) # CACHE STRING)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set_lib_path(PYTHON "python")
|
set_lib_path(PYTHON "python")
|
||||||
STRING(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION})
|
STRING(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION})
|
||||||
set(PYTHON_LIBRARY ${PYTHON}/lib/python${_PYTHON_VERSION_NO_DOTS}.lib) #CACHE FILEPATH
|
# Use shared libs for vc2008 and vc2010 until we actually have vc2010 libs
|
||||||
|
set(PYTHON_LIBRARY ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}.lib)
|
||||||
|
# set(PYTHON_LIBRARY ${PYTHON}/lib/python${_PYTHON_VERSION_NO_DOTS}.lib) #CACHE FILEPATH
|
||||||
unset(_PYTHON_VERSION_NO_DOTS)
|
unset(_PYTHON_VERSION_NO_DOTS)
|
||||||
|
|
||||||
#Shared includes for both vc2008 and vc2010
|
#Shared includes for both vc2008 and vc2010
|
||||||
@@ -1836,6 +1849,20 @@ else()
|
|||||||
set(GLEW_INCLUDE_PATH "${CMAKE_SOURCE_DIR}/extern/glew/include")
|
set(GLEW_INCLUDE_PATH "${CMAKE_SOURCE_DIR}/extern/glew/include")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Configure Bullet
|
||||||
|
|
||||||
|
if(WITH_BULLET AND WITH_SYSTEM_BULLET)
|
||||||
|
find_package(Bullet)
|
||||||
|
if(NOT BULLET_FOUND)
|
||||||
|
set(WITH_BULLET OFF)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set(BULLET_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/extern/bullet2/src")
|
||||||
|
# set(BULLET_LIBRARIES "")
|
||||||
|
endif()
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
# Configure Python.
|
# Configure Python.
|
||||||
|
|
||||||
@@ -2140,3 +2167,8 @@ if(FIRST_RUN)
|
|||||||
|
|
||||||
message("${_config_msg}")
|
message("${_config_msg}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# debug
|
||||||
|
message(
|
||||||
|
STATUS "HAVE_STDBOOL_H = ${HAVE_STDBOOL_H}"
|
||||||
|
)
|
||||||
|
12
SConstruct
12
SConstruct
@@ -374,9 +374,10 @@ if btools.ENDIAN == "big":
|
|||||||
else:
|
else:
|
||||||
env['CPPFLAGS'].append('-D__LITTLE_ENDIAN__')
|
env['CPPFLAGS'].append('-D__LITTLE_ENDIAN__')
|
||||||
|
|
||||||
# TODO, make optional
|
# TODO, make optional (as with CMake)
|
||||||
env['CPPFLAGS'].append('-DWITH_AUDASPACE')
|
env['CPPFLAGS'].append('-DWITH_AUDASPACE')
|
||||||
env['CPPFLAGS'].append('-DWITH_AVI')
|
env['CPPFLAGS'].append('-DWITH_AVI')
|
||||||
|
env['CPPFLAGS'].append('-DWITH_BOOL_COMPAT')
|
||||||
|
|
||||||
# lastly we check for root_build_dir ( we should not do before, otherwise we might do wrong builddir
|
# lastly we check for root_build_dir ( we should not do before, otherwise we might do wrong builddir
|
||||||
B.root_build_dir = env['BF_BUILDDIR']
|
B.root_build_dir = env['BF_BUILDDIR']
|
||||||
@@ -443,11 +444,12 @@ if env['WITH_BF_PYTHON']:
|
|||||||
found_pyconfig_h = True
|
found_pyconfig_h = True
|
||||||
|
|
||||||
if not (found_python_h and found_pyconfig_h):
|
if not (found_python_h and found_pyconfig_h):
|
||||||
print("\nMissing: Python.h and/or pyconfig.h in\"" + env.subst('${BF_PYTHON_INC}') + "\",\n"
|
print("""\nMissing: Python.h and/or pyconfig.h in "%s"
|
||||||
" Set 'BF_PYTHON_INC' to point "
|
Set 'BF_PYTHON_INC' to point to valid include path(s),
|
||||||
"to valid python include path(s).\n Containing "
|
containing Python.h and pyconfig.h for Python version "%s".
|
||||||
"Python.h and pyconfig.h for python version \"" + env.subst('${BF_PYTHON_VERSION}') + "\"")
|
|
||||||
|
|
||||||
|
Example: python scons/scons.py BF_PYTHON_INC=../Python/include
|
||||||
|
""" % (env.subst('${BF_PYTHON_INC}'), env.subst('${BF_PYTHON_VERSION}')))
|
||||||
Exit()
|
Exit()
|
||||||
|
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -66,6 +66,7 @@ SET(_opencollada_SEARCH_DIRS
|
|||||||
/sw # Fink
|
/sw # Fink
|
||||||
/opt/local # DarwinPorts
|
/opt/local # DarwinPorts
|
||||||
/opt/csw # Blastwave
|
/opt/csw # Blastwave
|
||||||
|
/opt/lib/opencollada
|
||||||
)
|
)
|
||||||
|
|
||||||
SET(_opencollada_INCLUDES)
|
SET(_opencollada_INCLUDES)
|
||||||
|
@@ -75,12 +75,12 @@ def is_cmake(filename):
|
|||||||
|
|
||||||
def is_c_header(filename):
|
def is_c_header(filename):
|
||||||
ext = splitext(filename)[1]
|
ext = splitext(filename)[1]
|
||||||
return (ext in (".h", ".hpp", ".hxx"))
|
return (ext in {".h", ".hpp", ".hxx", ".hh"})
|
||||||
|
|
||||||
|
|
||||||
def is_c(filename):
|
def is_c(filename):
|
||||||
ext = splitext(filename)[1]
|
ext = splitext(filename)[1]
|
||||||
return (ext in (".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl"))
|
return (ext in {".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl"})
|
||||||
|
|
||||||
|
|
||||||
def is_c_any(filename):
|
def is_c_any(filename):
|
||||||
|
@@ -282,7 +282,9 @@ macro(setup_liblinks
|
|||||||
if(WITH_SYSTEM_GLEW)
|
if(WITH_SYSTEM_GLEW)
|
||||||
target_link_libraries(${target} ${GLEW_LIBRARY})
|
target_link_libraries(${target} ${GLEW_LIBRARY})
|
||||||
endif()
|
endif()
|
||||||
|
if(WITH_BULLET AND WITH_SYSTEM_BULLET)
|
||||||
|
target_link_libraries(${target} ${BULLET_LIBRARIES})
|
||||||
|
endif()
|
||||||
if(WITH_OPENAL)
|
if(WITH_OPENAL)
|
||||||
target_link_libraries(${target} ${OPENAL_LIBRARY})
|
target_link_libraries(${target} ${OPENAL_LIBRARY})
|
||||||
endif()
|
endif()
|
||||||
@@ -441,6 +443,15 @@ macro(TEST_SSE_SUPPORT
|
|||||||
unset(CMAKE_REQUIRED_FLAGS)
|
unset(CMAKE_REQUIRED_FLAGS)
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
macro(TEST_STDBOOL_SUPPORT)
|
||||||
|
# This program will compile correctly if and only if
|
||||||
|
# this C compiler supports C99 stdbool.
|
||||||
|
check_c_source_runs("
|
||||||
|
#include <stdbool.h>
|
||||||
|
int main(void) { return (int)false; }"
|
||||||
|
HAVE_STDBOOL_H)
|
||||||
|
endmacro()
|
||||||
|
|
||||||
# when we have warnings as errors applied globally this
|
# when we have warnings as errors applied globally this
|
||||||
# needs to be removed for some external libs which we dont maintain.
|
# needs to be removed for some external libs which we dont maintain.
|
||||||
|
|
||||||
|
@@ -97,7 +97,7 @@ def is_cmake(filename):
|
|||||||
|
|
||||||
def is_c_header(filename):
|
def is_c_header(filename):
|
||||||
ext = splitext(filename)[1]
|
ext = splitext(filename)[1]
|
||||||
return (ext in (".h", ".hpp", ".hxx"))
|
return (ext in {".h", ".hpp", ".hxx", ".hh"})
|
||||||
|
|
||||||
|
|
||||||
def is_py(filename):
|
def is_py(filename):
|
||||||
|
@@ -43,7 +43,7 @@ SOURCE_DIR = abspath(SOURCE_DIR)
|
|||||||
|
|
||||||
def is_c_header(filename):
|
def is_c_header(filename):
|
||||||
ext = os.path.splitext(filename)[1]
|
ext = os.path.splitext(filename)[1]
|
||||||
return (ext in (".h", ".hpp", ".hxx"))
|
return (ext in {".h", ".hpp", ".hxx", ".hh"})
|
||||||
|
|
||||||
|
|
||||||
def is_c(filename):
|
def is_c(filename):
|
||||||
|
@@ -77,6 +77,7 @@ fi || :
|
|||||||
%{_bindir}/%{name}
|
%{_bindir}/%{name}
|
||||||
%{_datadir}/%{name}/%{blender_api}/datafiles/fonts
|
%{_datadir}/%{name}/%{blender_api}/datafiles/fonts
|
||||||
%{_datadir}/%{name}/%{blender_api}/datafiles/colormanagement
|
%{_datadir}/%{name}/%{blender_api}/datafiles/colormanagement
|
||||||
|
%{_datadir}/%{name}/%{blender_api}/datafiles/locale/languages
|
||||||
%{_datadir}/%{name}/%{blender_api}/scripts
|
%{_datadir}/%{name}/%{blender_api}/scripts
|
||||||
%{_datadir}/icons/hicolor/*/apps/%{name}.*
|
%{_datadir}/icons/hicolor/*/apps/%{name}.*
|
||||||
%{_datadir}/applications/%{name}.desktop
|
%{_datadir}/applications/%{name}.desktop
|
||||||
|
70
doc/python_api/examples/bpy.types.AddonPreferences.1.py
Normal file
70
doc/python_api/examples/bpy.types.AddonPreferences.1.py
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
bl_info = {
|
||||||
|
"name": "Example Addon Preferences",
|
||||||
|
"author": "Your Name Here",
|
||||||
|
"version": (1, 0),
|
||||||
|
"blender": (2, 65, 0),
|
||||||
|
"location": "SpaceBar Search -> Addon Preferences Example",
|
||||||
|
"description": "Example Addon",
|
||||||
|
"warning": "",
|
||||||
|
"wiki_url": "",
|
||||||
|
"tracker_url": "",
|
||||||
|
"category": "Object"}
|
||||||
|
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
from bpy.types import Operator, AddonPreferences
|
||||||
|
from bpy.props import StringProperty, IntProperty, BoolProperty
|
||||||
|
|
||||||
|
|
||||||
|
class ExampleAddonPreferences(AddonPreferences):
|
||||||
|
bl_idname = __name__
|
||||||
|
|
||||||
|
filepath = StringProperty(
|
||||||
|
name="Example File Path",
|
||||||
|
subtype='FILE_PATH',
|
||||||
|
)
|
||||||
|
number = IntProperty(
|
||||||
|
name="Example Number",
|
||||||
|
default=4,
|
||||||
|
)
|
||||||
|
boolean = BoolProperty(
|
||||||
|
name="Example Boolean",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
layout.label(text="This is a preferences view for our addon")
|
||||||
|
layout.prop(self, "filepath")
|
||||||
|
layout.prop(self, "number")
|
||||||
|
layout.prop(self, "boolean")
|
||||||
|
|
||||||
|
|
||||||
|
class OBJECT_OT_addon_prefs_example(Operator):
|
||||||
|
"""Display example preferences"""
|
||||||
|
bl_idname = "object.addon_prefs_example"
|
||||||
|
bl_label = "Addon Preferences Example"
|
||||||
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
user_preferences = context.user_preferences
|
||||||
|
addon_prefs = user_preferences.addons[__name__].preferences
|
||||||
|
|
||||||
|
info = ("Path: %s, Number: %d, Boolean %r" %
|
||||||
|
(addon_prefs.filepath, addon_prefs.number, addon_prefs.boolean))
|
||||||
|
|
||||||
|
self.report({'INFO'}, info)
|
||||||
|
print(info)
|
||||||
|
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
|
# Registration
|
||||||
|
def register():
|
||||||
|
bpy.utils.register_class(OBJECT_OT_addon_prefs_example)
|
||||||
|
bpy.utils.register_class(ExampleAddonPreferences)
|
||||||
|
|
||||||
|
|
||||||
|
def unregister():
|
||||||
|
bpy.utils.unregister_class(OBJECT_OT_addon_prefs_example)
|
||||||
|
bpy.utils.unregister_class(ExampleAddonPreferences)
|
89
doc/python_api/examples/bpy.types.UIList.py
Normal file
89
doc/python_api/examples/bpy.types.UIList.py
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
"""
|
||||||
|
Basic UIList Example
|
||||||
|
+++++++++++++++++++
|
||||||
|
This script is the UIList subclass used to show material slots, with a bunch of additional commentaries.
|
||||||
|
|
||||||
|
Notice the name of the class, this naming convention is similar as the one for panels or menus.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
UIList subclasses must be registered for blender to use them.
|
||||||
|
"""
|
||||||
|
import bpy
|
||||||
|
|
||||||
|
|
||||||
|
class MATERIAL_UL_matslots_example(bpy.types.UIList):
|
||||||
|
# The draw_item function is called for each item of the collection that is visible in the list.
|
||||||
|
# data is the RNA object containing the collection,
|
||||||
|
# item is the current drawn item of the collection,
|
||||||
|
# icon is the "computed" icon for the item (as an integer, because some objects like materials or textures
|
||||||
|
# have custom icons ID, which are not available as enum items).
|
||||||
|
# active_data is the RNA object containing the active property for the collection (i.e. integer pointing to the
|
||||||
|
# active item of the collection).
|
||||||
|
# active_propname is the name of the active property (use 'getattr(active_data, active_propname)').
|
||||||
|
# index is index of the current item in the collection.
|
||||||
|
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
|
||||||
|
ob = data
|
||||||
|
slot = item
|
||||||
|
ma = slot.material
|
||||||
|
# draw_item must handle the three layout types... Usually 'DEFAULT' and 'COMPACT' can share the same code.
|
||||||
|
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
||||||
|
# You should always start your row layout by a label (icon + text), this will also make the row easily
|
||||||
|
# selectable in the list!
|
||||||
|
# We use icon_value of label, as our given icon is an integer value, not an enum ID.
|
||||||
|
layout.label(ma.name if ma else "", icon_value=icon)
|
||||||
|
# And now we can add other UI stuff...
|
||||||
|
# Here, we add nodes info if this material uses (old!) shading nodes.
|
||||||
|
if ma and not context.scene.render.use_shading_nodes:
|
||||||
|
manode = ma.active_node_material
|
||||||
|
if manode:
|
||||||
|
# The static method UILayout.icon returns the integer value of the icon ID "computed" for the given
|
||||||
|
# RNA object.
|
||||||
|
layout.label("Node %s" % manode.name, icon_value=layout.icon(manode))
|
||||||
|
elif ma.use_nodes:
|
||||||
|
layout.label("Node <none>")
|
||||||
|
else:
|
||||||
|
layout.label("")
|
||||||
|
# 'GRID' layout type should be as compact as possible (typically a single icon!).
|
||||||
|
elif self.layout_type in {'GRID'}:
|
||||||
|
layout.alignment = 'CENTER'
|
||||||
|
layout.label("", icon_value=icon)
|
||||||
|
|
||||||
|
|
||||||
|
# And now we can use this list everywhere in Blender. Here is a small example panel.
|
||||||
|
class UIListPanelExample(bpy.types.Panel):
|
||||||
|
"""Creates a Panel in the Object properties window"""
|
||||||
|
bl_label = "UIList Panel"
|
||||||
|
bl_idname = "OBJECT_PT_ui_list_example"
|
||||||
|
bl_space_type = 'PROPERTIES'
|
||||||
|
bl_region_type = 'WINDOW'
|
||||||
|
bl_context = "object"
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
|
||||||
|
obj = context.object
|
||||||
|
|
||||||
|
# template_list now takes two new args.
|
||||||
|
# The first one is the identifier of the registered UIList to use (if you want only the default list,
|
||||||
|
# with no custom draw code, use "UI_UL_list").
|
||||||
|
layout.template_list("MATERIAL_UL_matslots_example", "", obj, "material_slots", obj, "active_material_index")
|
||||||
|
|
||||||
|
# The second one can usually be left as an empty string. It's an additional ID used to distinguish lists in case you
|
||||||
|
# use the same list several times in a given area.
|
||||||
|
layout.template_list("MATERIAL_UL_matslots_example", "compact", obj, "material_slots",
|
||||||
|
obj, "active_material_index", type='COMPACT')
|
||||||
|
|
||||||
|
|
||||||
|
def register():
|
||||||
|
bpy.utils.register_class(MATERIAL_UL_matslots_example)
|
||||||
|
bpy.utils.register_class(UIListPanelExample)
|
||||||
|
|
||||||
|
|
||||||
|
def unregister():
|
||||||
|
bpy.utils.unregister_class(MATERIAL_UL_matslots_example)
|
||||||
|
bpy.utils.unregister_class(UIListPanelExample)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
register()
|
@@ -3749,6 +3749,18 @@ Types
|
|||||||
|
|
||||||
:type: float
|
:type: float
|
||||||
|
|
||||||
|
.. attribute:: maxJumps
|
||||||
|
|
||||||
|
The maximum number of jumps a character can perform before having to touch the ground. By default this is set to 1. 2 allows for a double jump, etc.
|
||||||
|
|
||||||
|
:type: int
|
||||||
|
|
||||||
|
.. attribute:: jumpCount
|
||||||
|
|
||||||
|
The current jump count. This can be used to have different logic for a single jump versus a double jump. For example, a different animation for the second jump.
|
||||||
|
|
||||||
|
:type: int
|
||||||
|
|
||||||
.. method:: jump()
|
.. method:: jump()
|
||||||
|
|
||||||
The character jumps based on it's jump speed.
|
The character jumps based on it's jump speed.
|
||||||
|
@@ -614,6 +614,10 @@ def pyfunc2sphinx(ident, fw, identifier, py_func, is_class=True):
|
|||||||
'''
|
'''
|
||||||
function or class method to sphinx
|
function or class method to sphinx
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
if type(py_func) == type(bpy.types.Space.draw_handler_add):
|
||||||
|
return
|
||||||
|
|
||||||
arg_str = inspect.formatargspec(*inspect.getargspec(py_func))
|
arg_str = inspect.formatargspec(*inspect.getargspec(py_func))
|
||||||
|
|
||||||
if not is_class:
|
if not is_class:
|
||||||
|
5
extern/CMakeLists.txt
vendored
5
extern/CMakeLists.txt
vendored
@@ -27,9 +27,12 @@
|
|||||||
remove_strict_flags()
|
remove_strict_flags()
|
||||||
|
|
||||||
add_subdirectory(colamd)
|
add_subdirectory(colamd)
|
||||||
|
add_subdirectory(rangetree)
|
||||||
|
|
||||||
if(WITH_BULLET)
|
if(WITH_BULLET)
|
||||||
add_subdirectory(bullet2)
|
if(NOT WITH_SYSTEM_BULLET)
|
||||||
|
add_subdirectory(bullet2)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# now only available in a branch
|
# now only available in a branch
|
||||||
|
1
extern/SConscript
vendored
1
extern/SConscript
vendored
@@ -4,6 +4,7 @@ Import('env')
|
|||||||
|
|
||||||
SConscript(['glew/SConscript'])
|
SConscript(['glew/SConscript'])
|
||||||
SConscript(['colamd/SConscript'])
|
SConscript(['colamd/SConscript'])
|
||||||
|
SConscript(['rangetree/SConscript'])
|
||||||
|
|
||||||
if env['WITH_BF_GAMEENGINE']:
|
if env['WITH_BF_GAMEENGINE']:
|
||||||
SConscript(['recastnavigation/SConscript'])
|
SConscript(['recastnavigation/SConscript'])
|
||||||
|
31
extern/rangetree/CMakeLists.txt
vendored
Normal file
31
extern/rangetree/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
#
|
||||||
|
# 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 2
|
||||||
|
# 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, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# ***** END GPL LICENSE BLOCK *****
|
||||||
|
|
||||||
|
set(INC
|
||||||
|
.
|
||||||
|
)
|
||||||
|
|
||||||
|
set(SRC
|
||||||
|
range_tree.hh
|
||||||
|
range_tree_c_api.h
|
||||||
|
|
||||||
|
range_tree_c_api.cc
|
||||||
|
)
|
||||||
|
|
||||||
|
blender_add_lib(extern_rangetree "${SRC}" "${INC}" "")
|
||||||
|
|
13
extern/rangetree/README.org
vendored
Normal file
13
extern/rangetree/README.org
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
* Overview
|
||||||
|
Basic class for storing non-overlapping scalar ranges. Underlying
|
||||||
|
representation is a C++ STL set for fast lookups.
|
||||||
|
|
||||||
|
* License
|
||||||
|
GPL version 2 or later (see COPYING)
|
||||||
|
|
||||||
|
* Author Note
|
||||||
|
This implementation is intended for storing free unique IDs in a new
|
||||||
|
undo system for BMesh in Blender, but could be useful elsewhere.
|
||||||
|
|
||||||
|
* Website
|
||||||
|
https://github.com/nicholasbishop/RangeTree
|
9
extern/rangetree/SConscript
vendored
Normal file
9
extern/rangetree/SConscript
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
2#!/usr/bin/python
|
||||||
|
Import ('env')
|
||||||
|
|
||||||
|
sources = env.Glob('*.cc')
|
||||||
|
|
||||||
|
incs = '.'
|
||||||
|
defs = ''
|
||||||
|
|
||||||
|
env.BlenderLib ('extern_rangetree', sources, Split(incs), Split(defs), libtype=['extern'], priority=[100] )
|
228
extern/rangetree/range_tree.hh
vendored
Normal file
228
extern/rangetree/range_tree.hh
vendored
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
/* 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 2 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, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <climits>
|
||||||
|
#include <iostream>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#ifndef RANGE_TREE_DEBUG_PRINT_FUNCTION
|
||||||
|
# define RANGE_TREE_DEBUG_PRINT_FUNCTION 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct RangeTree {
|
||||||
|
struct Range {
|
||||||
|
Range(T min_, T max_)
|
||||||
|
: min(min_), max(max_), single(min_ == max_) {
|
||||||
|
assert(min_ <= max_);
|
||||||
|
}
|
||||||
|
|
||||||
|
Range(T t)
|
||||||
|
: min(t), max(t), single(true)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool operator<(const Range& v) const {
|
||||||
|
return max < v.min;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T min;
|
||||||
|
const T max;
|
||||||
|
const bool single;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::set<Range> Tree;
|
||||||
|
typedef typename Tree::iterator TreeIter;
|
||||||
|
typedef typename Tree::reverse_iterator TreeIterReverse;
|
||||||
|
typedef typename Tree::const_iterator TreeIterConst;
|
||||||
|
|
||||||
|
/* Initialize with a single range from 'min' to 'max', inclusive. */
|
||||||
|
RangeTree(T min, T max) {
|
||||||
|
tree.insert(Range(min, max));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize with a single range from 0 to 'max', inclusive. */
|
||||||
|
RangeTree(T max) {
|
||||||
|
tree.insert(Range(0, max));
|
||||||
|
}
|
||||||
|
|
||||||
|
RangeTree(const RangeTree<T>& src) {
|
||||||
|
tree = src.tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove 't' from the associated range in the tree. Precondition:
|
||||||
|
a range including 't' must exist in the tree. */
|
||||||
|
void take(T t) {
|
||||||
|
#if RANGE_TREE_DEBUG_PRINT_FUNCTION
|
||||||
|
std::cout << __func__ << "(" << t << ")\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Find the range that includes 't' and its neighbors */
|
||||||
|
TreeIter iter = tree.find(Range(t));
|
||||||
|
assert(iter != tree.end());
|
||||||
|
Range cur = *iter;
|
||||||
|
TreeIter prev = iter;
|
||||||
|
TreeIter next = iter;
|
||||||
|
--prev;
|
||||||
|
++next;
|
||||||
|
|
||||||
|
/* Remove the original range (note that this does not
|
||||||
|
invalidate the prev/next iterators) */
|
||||||
|
tree.erase(iter);
|
||||||
|
|
||||||
|
/* Construct two new ranges that together cover the original
|
||||||
|
range, except for 't' */
|
||||||
|
if (t > cur.min)
|
||||||
|
tree.insert(Range(cur.min, t - 1));
|
||||||
|
if (t + 1 <= cur.max)
|
||||||
|
tree.insert(Range(t + 1, cur.max));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Take the first element out of the first range in the
|
||||||
|
tree. Precondition: tree must not be empty. */
|
||||||
|
T take_any() {
|
||||||
|
#if RANGE_TREE_DEBUG_PRINT_FUNCTION
|
||||||
|
std::cout << __func__ << "()\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Find the first element */
|
||||||
|
TreeIter iter = tree.begin();
|
||||||
|
assert(iter != tree.end());
|
||||||
|
T first = iter->min;
|
||||||
|
|
||||||
|
/* Take the first element */
|
||||||
|
take(first);
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return 't' to the tree, either expanding/merging existing
|
||||||
|
ranges or adding a range to cover it. Precondition: 't' cannot
|
||||||
|
be in an existing range. */
|
||||||
|
void release(T t) {
|
||||||
|
#if RANGE_TREE_DEBUG_PRINT_FUNCTION
|
||||||
|
std::cout << __func__ << "(" << t << ")\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* TODO: these cases should be simplified/unified */
|
||||||
|
|
||||||
|
TreeIter right = tree.upper_bound(t);
|
||||||
|
if (right != tree.end()) {
|
||||||
|
TreeIter left = right;
|
||||||
|
if (left != tree.begin())
|
||||||
|
--left;
|
||||||
|
|
||||||
|
if (left == right) {
|
||||||
|
/* 't' lies before any existing ranges */
|
||||||
|
if (t + 1 == left->min) {
|
||||||
|
/* 't' lies directly before the first range,
|
||||||
|
resize and replace that range */
|
||||||
|
const Range r(t, left->max);
|
||||||
|
tree.erase(left);
|
||||||
|
tree.insert(r);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* There's a gap between 't' and the first range,
|
||||||
|
add a new range */
|
||||||
|
tree.insert(Range(t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((left->max + 1 == t) &&
|
||||||
|
(t + 1 == right->min)) {
|
||||||
|
/* 't' fills a hole. Remove left and right, and insert a
|
||||||
|
new range that covers both. */
|
||||||
|
const Range r(left->min, right->max);
|
||||||
|
tree.erase(left);
|
||||||
|
tree.erase(right);
|
||||||
|
tree.insert(r);
|
||||||
|
}
|
||||||
|
else if (left->max + 1 == t) {
|
||||||
|
/* 't' lies directly after 'left' range, resize and
|
||||||
|
replace that range */
|
||||||
|
const Range r(left->min, t);
|
||||||
|
tree.erase(left);
|
||||||
|
tree.insert(r);
|
||||||
|
}
|
||||||
|
else if (t + 1 == right->min) {
|
||||||
|
/* 't' lies directly before 'right' range, resize and
|
||||||
|
replace that range */
|
||||||
|
const Range r(t, right->max);
|
||||||
|
tree.erase(right);
|
||||||
|
tree.insert(r);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* There's a gap between 't' and both adjacent ranges,
|
||||||
|
add a new range */
|
||||||
|
tree.insert(Range(t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* 't' lies after any existing ranges */
|
||||||
|
right = tree.end();
|
||||||
|
right--;
|
||||||
|
if (right->max + 1 == t) {
|
||||||
|
/* 't' lies directly after last range, resize and
|
||||||
|
replace that range */
|
||||||
|
const Range r(right->min, t);
|
||||||
|
tree.erase(right);
|
||||||
|
tree.insert(r);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* There's a gap between the last range and 't', add a
|
||||||
|
new range */
|
||||||
|
tree.insert(Range(t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has(T t) const {
|
||||||
|
TreeIterConst iter = tree.find(Range(t));
|
||||||
|
return (iter != tree.end()) && (t <= iter->max);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_range(T min, T max) const {
|
||||||
|
TreeIterConst iter = tree.find(Range(min, max));
|
||||||
|
return (iter != tree.end()) && (min == iter->min && max == iter->max);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const {
|
||||||
|
return tree.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
int size() const {
|
||||||
|
return tree.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void print() const {
|
||||||
|
std::cout << "RangeTree:\n";
|
||||||
|
for (TreeIterConst iter = tree.begin(); iter != tree.end(); ++iter) {
|
||||||
|
const Range& r = *iter;
|
||||||
|
if (r.single)
|
||||||
|
std::cout << " [" << r.min << "]\n";
|
||||||
|
else
|
||||||
|
std::cout << " [" << r.min << ", " << r.max << "]\n";
|
||||||
|
}
|
||||||
|
if (empty())
|
||||||
|
std::cout << " <empty>";
|
||||||
|
std::cout << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int allocation_lower_bound() const {
|
||||||
|
return tree.size() * sizeof(Range);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Tree tree;
|
||||||
|
};
|
86
extern/rangetree/range_tree_c_api.cc
vendored
Normal file
86
extern/rangetree/range_tree_c_api.cc
vendored
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/* 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 2 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, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "range_tree.hh"
|
||||||
|
|
||||||
|
/* Give RangeTreeUInt a real type rather than the opaque struct type
|
||||||
|
defined for external use. */
|
||||||
|
#define RANGE_TREE_C_API_INTERNAL
|
||||||
|
typedef RangeTree<unsigned> RangeTreeUInt;
|
||||||
|
|
||||||
|
#include "range_tree_c_api.h"
|
||||||
|
|
||||||
|
RangeTreeUInt *range_tree_uint_alloc(unsigned min, unsigned max)
|
||||||
|
{
|
||||||
|
return new RangeTreeUInt(min, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
RangeTreeUInt *range_tree_uint_copy(RangeTreeUInt *src)
|
||||||
|
{
|
||||||
|
return new RangeTreeUInt(*src);
|
||||||
|
}
|
||||||
|
|
||||||
|
void range_tree_uint_free(RangeTreeUInt *rt)
|
||||||
|
{
|
||||||
|
delete rt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void range_tree_uint_take(RangeTreeUInt *rt, unsigned v)
|
||||||
|
{
|
||||||
|
rt->take(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned range_tree_uint_take_any(RangeTreeUInt *rt)
|
||||||
|
{
|
||||||
|
return rt->take_any();
|
||||||
|
}
|
||||||
|
|
||||||
|
void range_tree_uint_release(RangeTreeUInt *rt, unsigned v)
|
||||||
|
{
|
||||||
|
rt->release(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
int range_tree_uint_has(const RangeTreeUInt *rt, unsigned v)
|
||||||
|
{
|
||||||
|
return rt->has(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
int range_tree_uint_has_range(const RangeTreeUInt *rt,
|
||||||
|
unsigned vmin,
|
||||||
|
unsigned vmax)
|
||||||
|
{
|
||||||
|
return rt->has_range(vmin, vmax);
|
||||||
|
}
|
||||||
|
|
||||||
|
int range_tree_uint_empty(const RangeTreeUInt *rt)
|
||||||
|
{
|
||||||
|
return rt->empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned range_tree_uint_size(const RangeTreeUInt *rt)
|
||||||
|
{
|
||||||
|
return rt->size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void range_tree_uint_print(const RangeTreeUInt *rt)
|
||||||
|
{
|
||||||
|
rt->print();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int range_tree_uint_allocation_lower_bound(const RangeTreeUInt *rt)
|
||||||
|
{
|
||||||
|
return rt->allocation_lower_bound();
|
||||||
|
}
|
60
extern/rangetree/range_tree_c_api.h
vendored
Normal file
60
extern/rangetree/range_tree_c_api.h
vendored
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/* 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 2 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, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RANGE_TREE_C_API_H
|
||||||
|
#define RANGE_TREE_C_API_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Simple C-accessible wrapper for RangeTree<unsigned> */
|
||||||
|
|
||||||
|
#ifndef RANGE_TREE_C_API_INTERNAL
|
||||||
|
typedef struct RangeTreeUInt RangeTreeUInt;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RangeTreeUInt *range_tree_uint_alloc(unsigned min, unsigned max);
|
||||||
|
|
||||||
|
RangeTreeUInt *range_tree_uint_copy(RangeTreeUInt *src);
|
||||||
|
|
||||||
|
void range_tree_uint_free(RangeTreeUInt *rt);
|
||||||
|
|
||||||
|
void range_tree_uint_take(RangeTreeUInt *rt, unsigned v);
|
||||||
|
|
||||||
|
unsigned range_tree_uint_take_any(RangeTreeUInt *rt);
|
||||||
|
|
||||||
|
void range_tree_uint_release(RangeTreeUInt *rt, unsigned v);
|
||||||
|
|
||||||
|
int range_tree_uint_has(const RangeTreeUInt *rt, unsigned v);
|
||||||
|
|
||||||
|
int range_tree_uint_has_range(const RangeTreeUInt *rt,
|
||||||
|
unsigned vmin,
|
||||||
|
unsigned vmax);
|
||||||
|
|
||||||
|
int range_tree_uint_empty(const RangeTreeUInt *rt);
|
||||||
|
|
||||||
|
unsigned range_tree_uint_size(const RangeTreeUInt *rt);
|
||||||
|
|
||||||
|
void range_tree_uint_print(const RangeTreeUInt *rt);
|
||||||
|
|
||||||
|
unsigned int range_tree_uint_allocation_lower_bound(const RangeTreeUInt *rt);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __DUALCON_H__ */
|
@@ -24,6 +24,7 @@ set(SRC
|
|||||||
blender_mesh.cpp
|
blender_mesh.cpp
|
||||||
blender_object.cpp
|
blender_object.cpp
|
||||||
blender_particles.cpp
|
blender_particles.cpp
|
||||||
|
blender_curves.cpp
|
||||||
blender_python.cpp
|
blender_python.cpp
|
||||||
blender_session.cpp
|
blender_session.cpp
|
||||||
blender_shader.cpp
|
blender_shader.cpp
|
||||||
|
@@ -21,7 +21,7 @@
|
|||||||
bl_info = {
|
bl_info = {
|
||||||
"name": "Cycles Render Engine",
|
"name": "Cycles Render Engine",
|
||||||
"author": "",
|
"author": "",
|
||||||
"blender": (2, 6, 5),
|
"blender": (2, 60, 5),
|
||||||
"location": "Info header, render engine menu",
|
"location": "Info header, render engine menu",
|
||||||
"description": "Cycles Render Engine integration",
|
"description": "Cycles Render Engine integration",
|
||||||
"warning": "",
|
"warning": "",
|
||||||
|
@@ -64,6 +64,38 @@ enum_panorama_types = (
|
|||||||
"Similar to most fisheye modern lens, takes sensor dimensions into consideration"),
|
"Similar to most fisheye modern lens, takes sensor dimensions into consideration"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
enum_curve_presets = (
|
||||||
|
('CUSTOM', "Custom", "Set general parameters"),
|
||||||
|
('TANGENT_SHADING', "Tangent Normal", "Use planar geometry and tangent normals"),
|
||||||
|
('TRUE_NORMAL', "True Normal", "Use true normals (good for thin strands)"),
|
||||||
|
('ACCURATE_PRESET', "Accurate", "Use best settings (suitable for glass materials)"),
|
||||||
|
)
|
||||||
|
|
||||||
|
enum_curve_primitives = (
|
||||||
|
('TRIANGLES', "Triangles", "Create triangle geometry around strands"),
|
||||||
|
('LINE_SEGMENTS', "Line Segments", "Use line segment primitives"),
|
||||||
|
('CURVE_SEGMENTS', "?Curve Segments?", "Use curve segment primitives (not implemented)"),
|
||||||
|
)
|
||||||
|
|
||||||
|
enum_triangle_curves = (
|
||||||
|
('CAMERA', "Planes", "Create individual triangles forming planes that face camera"),
|
||||||
|
('RIBBONS', "Ribbons", "Create individual triangles forming ribbon"),
|
||||||
|
('TESSELLATED', "Tessellated", "Create mesh surrounding each strand"),
|
||||||
|
)
|
||||||
|
|
||||||
|
enum_line_curves = (
|
||||||
|
('ACCURATE', "Accurate", "Always take into consideration strand width for intersections"),
|
||||||
|
('QT_CORRECTED', "Corrected", "Ignore width for initial intersection and correct later"),
|
||||||
|
('ENDCORRECTED', "Correct found", "Ignore width for all intersections and only correct closest"),
|
||||||
|
('QT_UNCORRECTED', "Uncorrected", "Calculate intersections without considering width"),
|
||||||
|
)
|
||||||
|
|
||||||
|
enum_curves_interpolation = (
|
||||||
|
('LINEAR', "Linear interpolation", "Use Linear interpolation between segments"),
|
||||||
|
('CARDINAL', "Cardinal interpolation", "Use cardinal interpolation between segments"),
|
||||||
|
('BSPLINE', "B-spline interpolation", "Use b-spline interpolation between segments"),
|
||||||
|
)
|
||||||
|
|
||||||
class CyclesRenderSettings(bpy.types.PropertyGroup):
|
class CyclesRenderSettings(bpy.types.PropertyGroup):
|
||||||
@classmethod
|
@classmethod
|
||||||
def register(cls):
|
def register(cls):
|
||||||
@@ -237,7 +269,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
|
|||||||
)
|
)
|
||||||
cls.film_transparent = BoolProperty(
|
cls.film_transparent = BoolProperty(
|
||||||
name="Transparent",
|
name="Transparent",
|
||||||
description="World background is transparent",
|
description="World background is transparent with premultiplied alpha",
|
||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -573,6 +605,157 @@ class CyclesMeshSettings(bpy.types.PropertyGroup):
|
|||||||
del bpy.types.Curve.cycles
|
del bpy.types.Curve.cycles
|
||||||
del bpy.types.MetaBall.cycles
|
del bpy.types.MetaBall.cycles
|
||||||
|
|
||||||
|
class CyclesCurveRenderSettings(bpy.types.PropertyGroup):
|
||||||
|
@classmethod
|
||||||
|
def register(cls):
|
||||||
|
bpy.types.Scene.cycles_curves = PointerProperty(
|
||||||
|
name="Cycles Hair Rendering Settings",
|
||||||
|
description="Cycles hair rendering settings",
|
||||||
|
type=cls,
|
||||||
|
)
|
||||||
|
cls.preset = EnumProperty(
|
||||||
|
name="Mode",
|
||||||
|
description="Hair rendering mode",
|
||||||
|
items=enum_curve_presets,
|
||||||
|
default='TRUE_NORMAL',
|
||||||
|
)
|
||||||
|
cls.primitive = EnumProperty(
|
||||||
|
name="Primitive",
|
||||||
|
description="Type of primitive used for hair rendering",
|
||||||
|
items=enum_curve_primitives,
|
||||||
|
default='LINE_SEGMENTS',
|
||||||
|
)
|
||||||
|
cls.triangle_method = EnumProperty(
|
||||||
|
name="Mesh Geometry",
|
||||||
|
description="Method for creating triangle geometry",
|
||||||
|
items=enum_triangle_curves,
|
||||||
|
default='CAMERA',
|
||||||
|
)
|
||||||
|
cls.line_method = EnumProperty(
|
||||||
|
name="Intersection Method",
|
||||||
|
description="Method for line segment intersection",
|
||||||
|
items=enum_line_curves,
|
||||||
|
default='ACCURATE',
|
||||||
|
)
|
||||||
|
cls.interpolation = EnumProperty(
|
||||||
|
name="Interpolation",
|
||||||
|
description="Interpolation method",
|
||||||
|
items=enum_curves_interpolation,
|
||||||
|
default='BSPLINE',
|
||||||
|
)
|
||||||
|
cls.use_backfacing = BoolProperty(
|
||||||
|
name="Check back-faces",
|
||||||
|
description="Test back-faces of strands",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
cls.use_encasing = BoolProperty(
|
||||||
|
name="Exclude encasing",
|
||||||
|
description="Ignore strands encasing a ray's initial location",
|
||||||
|
default=True,
|
||||||
|
)
|
||||||
|
cls.use_tangent_normal_geometry = BoolProperty(
|
||||||
|
name="Tangent normal geometry",
|
||||||
|
description="Use the tangent normal for actual normal",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
cls.use_tangent_normal = BoolProperty(
|
||||||
|
name="Tangent normal default",
|
||||||
|
description="Use the tangent normal for all normals",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
cls.use_tangent_normal_correction = BoolProperty(
|
||||||
|
name="Strand slope correction",
|
||||||
|
description="Correct the tangent normal for the strand's slope",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
cls.use_cache = BoolProperty(
|
||||||
|
name="Export Cached data",
|
||||||
|
default=True,
|
||||||
|
)
|
||||||
|
cls.use_parents = BoolProperty(
|
||||||
|
name="Use parent strands",
|
||||||
|
description="Use parents with children",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
cls.use_smooth = BoolProperty(
|
||||||
|
name="Smooth Strands",
|
||||||
|
description="Use vertex normals",
|
||||||
|
default=True,
|
||||||
|
)
|
||||||
|
cls.use_joined = BoolProperty(
|
||||||
|
name="Join",
|
||||||
|
description="Fill gaps between segments (requires more memory)",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
cls.use_curves = BoolProperty(
|
||||||
|
name="Use Cycles Hair Rendering",
|
||||||
|
description="Activate Cycles hair rendering for particle system",
|
||||||
|
default=True,
|
||||||
|
)
|
||||||
|
cls.segments = IntProperty(
|
||||||
|
name="Segments",
|
||||||
|
description="Number of segments between path keys (note that this combines with the 'draw step' value)",
|
||||||
|
min=1, max=64,
|
||||||
|
default=1,
|
||||||
|
)
|
||||||
|
cls.resolution = IntProperty(
|
||||||
|
name="Resolution",
|
||||||
|
description="Resolution of generated mesh",
|
||||||
|
min=3, max=64,
|
||||||
|
default=3,
|
||||||
|
)
|
||||||
|
cls.normalmix = FloatProperty(
|
||||||
|
name="Normal mix",
|
||||||
|
description="Scale factor for tangent normal removal (zero gives ray normal)",
|
||||||
|
min=0, max=2.0,
|
||||||
|
default=1,
|
||||||
|
)
|
||||||
|
cls.encasing_ratio = FloatProperty(
|
||||||
|
name="Encasing ratio",
|
||||||
|
description="Scale factor for encasing strand width",
|
||||||
|
min=0, max=100.0,
|
||||||
|
default=1.01,
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def unregister(cls):
|
||||||
|
del bpy.types.Scene.cycles_curves
|
||||||
|
|
||||||
|
class CyclesCurveSettings(bpy.types.PropertyGroup):
|
||||||
|
@classmethod
|
||||||
|
def register(cls):
|
||||||
|
bpy.types.ParticleSettings.cycles = PointerProperty(
|
||||||
|
name="Cycles Hair Settings",
|
||||||
|
description="Cycles hair settings",
|
||||||
|
type=cls,
|
||||||
|
)
|
||||||
|
cls.root_width = FloatProperty(
|
||||||
|
name="Root Size Multiplier",
|
||||||
|
description="Multiplier of particle size for the strand's width at root",
|
||||||
|
min=0.0, max=1000.0,
|
||||||
|
default=1.0,
|
||||||
|
)
|
||||||
|
cls.tip_width = FloatProperty(
|
||||||
|
name="Tip Size Multiplier",
|
||||||
|
description="Multiplier of particle size for the strand's width at tip",
|
||||||
|
min=0.0, max=1000.0,
|
||||||
|
default=0.0,
|
||||||
|
)
|
||||||
|
cls.shape = FloatProperty(
|
||||||
|
name="Strand Shape",
|
||||||
|
description="Strand shape parameter",
|
||||||
|
min=-1.0, max=1.0,
|
||||||
|
default=0.0,
|
||||||
|
)
|
||||||
|
cls.use_closetip = BoolProperty(
|
||||||
|
name="Close tip",
|
||||||
|
description="Set tip radius to zero",
|
||||||
|
default=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def unregister(cls):
|
||||||
|
del bpy.types.ParticleSettings.cycles
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
bpy.utils.register_class(CyclesRenderSettings)
|
bpy.utils.register_class(CyclesRenderSettings)
|
||||||
@@ -582,6 +765,8 @@ def register():
|
|||||||
bpy.utils.register_class(CyclesWorldSettings)
|
bpy.utils.register_class(CyclesWorldSettings)
|
||||||
bpy.utils.register_class(CyclesVisibilitySettings)
|
bpy.utils.register_class(CyclesVisibilitySettings)
|
||||||
bpy.utils.register_class(CyclesMeshSettings)
|
bpy.utils.register_class(CyclesMeshSettings)
|
||||||
|
bpy.utils.register_class(CyclesCurveRenderSettings)
|
||||||
|
bpy.utils.register_class(CyclesCurveSettings)
|
||||||
|
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
@@ -592,3 +777,5 @@ def unregister():
|
|||||||
bpy.utils.unregister_class(CyclesWorldSettings)
|
bpy.utils.unregister_class(CyclesWorldSettings)
|
||||||
bpy.utils.unregister_class(CyclesMeshSettings)
|
bpy.utils.unregister_class(CyclesMeshSettings)
|
||||||
bpy.utils.unregister_class(CyclesVisibilitySettings)
|
bpy.utils.unregister_class(CyclesVisibilitySettings)
|
||||||
|
bpy.utils.unregister_class(CyclesCurveRenderSettings)
|
||||||
|
bpy.utils.unregister_class(CyclesCurveSettings)
|
||||||
|
@@ -290,7 +290,7 @@ class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
|
|||||||
rd = scene.render
|
rd = scene.render
|
||||||
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.template_list(rd, "layers", rd.layers, "active_index", rows=2)
|
row.template_list("RENDER_UL_renderlayers", "", rd, "layers", rd.layers, "active_index", rows=2)
|
||||||
|
|
||||||
col = row.column(align=True)
|
col = row.column(align=True)
|
||||||
col.operator("scene.render_layer_add", icon='ZOOMIN', text="")
|
col.operator("scene.render_layer_add", icon='ZOOMIN', text="")
|
||||||
@@ -407,7 +407,7 @@ class Cycles_PT_context_material(CyclesButtonsPanel, Panel):
|
|||||||
if ob:
|
if ob:
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
|
|
||||||
row.template_list(ob, "material_slots", ob, "active_material_index", rows=2)
|
row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=2)
|
||||||
|
|
||||||
col = row.column(align=True)
|
col = row.column(align=True)
|
||||||
col.operator("object.material_slot_add", icon='ZOOMIN', text="")
|
col.operator("object.material_slot_add", icon='ZOOMIN', text="")
|
||||||
@@ -962,7 +962,7 @@ class CyclesParticle_PT_textures(CyclesButtonsPanel, Panel):
|
|||||||
part = psys.settings
|
part = psys.settings
|
||||||
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.template_list(part, "texture_slots", part, "active_texture_index", rows=2)
|
row.template_list("TEXTURE_UL_texslots", "", part, "texture_slots", part, "active_texture_index", rows=2)
|
||||||
|
|
||||||
col = row.column(align=True)
|
col = row.column(align=True)
|
||||||
col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
|
col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
|
||||||
@@ -975,6 +975,89 @@ class CyclesParticle_PT_textures(CyclesButtonsPanel, Panel):
|
|||||||
slot = part.texture_slots[part.active_texture_index]
|
slot = part.texture_slots[part.active_texture_index]
|
||||||
layout.template_ID(slot, "texture", new="texture.new")
|
layout.template_ID(slot, "texture", new="texture.new")
|
||||||
|
|
||||||
|
class CyclesRender_PT_CurveRendering(CyclesButtonsPanel, Panel):
|
||||||
|
bl_label = "Cycles Hair Rendering"
|
||||||
|
bl_context = "particle"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
psys = context.particle_system
|
||||||
|
device_type = context.user_preferences.system.compute_device_type
|
||||||
|
experimental = context.scene.cycles.feature_set == 'EXPERIMENTAL' and (context.scene.cycles.device == 'CPU' or device_type == 'NONE')
|
||||||
|
return CyclesButtonsPanel.poll(context) and experimental and psys
|
||||||
|
|
||||||
|
def draw_header(self, context):
|
||||||
|
cscene = context.scene.cycles_curves
|
||||||
|
self.layout.prop(cscene, "use_curves", text="")
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
|
||||||
|
scene = context.scene
|
||||||
|
cscene = scene.cycles_curves
|
||||||
|
|
||||||
|
layout.active = cscene.use_curves
|
||||||
|
|
||||||
|
layout.prop(cscene, "preset", text="Mode")
|
||||||
|
|
||||||
|
if cscene.preset == 'CUSTOM':
|
||||||
|
layout.prop(cscene, "primitive", text="Primitive")
|
||||||
|
|
||||||
|
if cscene.primitive == 'TRIANGLES':
|
||||||
|
layout.prop(cscene, "triangle_method", text="Method")
|
||||||
|
if cscene.triangle_method == 'TESSELLATED':
|
||||||
|
layout.prop(cscene, "resolution", text="Resolution")
|
||||||
|
layout.prop(cscene, "use_smooth", text="Smooth")
|
||||||
|
elif cscene.primitive == 'LINE_SEGMENTS':
|
||||||
|
layout.prop(cscene, "use_backfacing", text="Check back-faces")
|
||||||
|
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(cscene, "use_encasing", text="Exclude encasing")
|
||||||
|
sub = row.row()
|
||||||
|
sub.active = cscene.use_encasing
|
||||||
|
sub.prop(cscene, "encasing_ratio", text="Ratio for encasing")
|
||||||
|
|
||||||
|
layout.prop(cscene, "line_method", text="Method")
|
||||||
|
layout.prop(cscene, "use_tangent_normal", text="Use tangent normal as default")
|
||||||
|
layout.prop(cscene, "use_tangent_normal_geometry", text="Use tangent normal geometry")
|
||||||
|
layout.prop(cscene, "use_tangent_normal_correction", text="Correct tangent normal for slope")
|
||||||
|
layout.prop(cscene, "interpolation", text="Interpolation")
|
||||||
|
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(cscene, "segments", text="Segments")
|
||||||
|
row.prop(cscene, "normalmix", text="Ray Mix")
|
||||||
|
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(cscene, "use_cache", text="Export cache with children")
|
||||||
|
if cscene.use_cache:
|
||||||
|
row.prop(cscene, "use_parents", text="Include parents")
|
||||||
|
|
||||||
|
class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel):
|
||||||
|
bl_label = "Cycles Hair Settings"
|
||||||
|
bl_context = "particle"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
use_curves = context.scene.cycles_curves.use_curves and context.particle_system
|
||||||
|
device_type = context.user_preferences.system.compute_device_type
|
||||||
|
experimental = context.scene.cycles.feature_set == 'EXPERIMENTAL' and (context.scene.cycles.device == 'CPU' or device_type == 'NONE')
|
||||||
|
return CyclesButtonsPanel.poll(context) and experimental and use_curves
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
|
||||||
|
psys = context.particle_settings
|
||||||
|
cpsys = psys.cycles
|
||||||
|
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(cpsys, "shape", text="Shape")
|
||||||
|
row.prop(cpsys, "use_closetip", text="Close tip")
|
||||||
|
|
||||||
|
layout.label(text="Width multiplier:")
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(cpsys, "root_width", text="Root")
|
||||||
|
row.prop(cpsys, "tip_width", text="Tip")
|
||||||
|
|
||||||
|
|
||||||
class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
|
class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
|
||||||
bl_label = "Simplify"
|
bl_label = "Simplify"
|
||||||
|
1130
intern/cycles/blender/blender_curves.cpp
Normal file
1130
intern/cycles/blender/blender_curves.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -147,7 +147,7 @@ static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_la
|
|||||||
if(active_render)
|
if(active_render)
|
||||||
attr = mesh->attributes.add(ATTR_STD_UV_TANGENT, name);
|
attr = mesh->attributes.add(ATTR_STD_UV_TANGENT, name);
|
||||||
else
|
else
|
||||||
attr = mesh->attributes.add(name, TypeDesc::TypeVector, Attribute::CORNER);
|
attr = mesh->attributes.add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
|
||||||
|
|
||||||
float3 *tangent = attr->data_float3();
|
float3 *tangent = attr->data_float3();
|
||||||
|
|
||||||
@@ -161,7 +161,7 @@ static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_la
|
|||||||
if(active_render)
|
if(active_render)
|
||||||
attr_sign = mesh->attributes.add(ATTR_STD_UV_TANGENT_SIGN, name_sign);
|
attr_sign = mesh->attributes.add(ATTR_STD_UV_TANGENT_SIGN, name_sign);
|
||||||
else
|
else
|
||||||
attr_sign = mesh->attributes.add(name_sign, TypeDesc::TypeFloat, Attribute::CORNER);
|
attr_sign = mesh->attributes.add(name_sign, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
|
||||||
|
|
||||||
tangent_sign = attr_sign->data_float();
|
tangent_sign = attr_sign->data_float();
|
||||||
}
|
}
|
||||||
@@ -223,10 +223,19 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
|
|||||||
int shader = used_shaders[mi];
|
int shader = used_shaders[mi];
|
||||||
bool smooth = f->use_smooth();
|
bool smooth = f->use_smooth();
|
||||||
|
|
||||||
mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
|
if(n == 4) {
|
||||||
|
if(len_squared(cross(mesh->verts[vi[1]] - mesh->verts[vi[0]], mesh->verts[vi[2]] - mesh->verts[vi[0]])) == 0.0f ||
|
||||||
if(n == 4)
|
len_squared(cross(mesh->verts[vi[2]] - mesh->verts[vi[0]], mesh->verts[vi[3]] - mesh->verts[vi[0]])) == 0.0f) {
|
||||||
mesh->add_triangle(vi[0], vi[2], vi[3], shader, smooth);
|
mesh->add_triangle(vi[0], vi[1], vi[3], shader, smooth);
|
||||||
|
mesh->add_triangle(vi[2], vi[3], vi[1], shader, smooth);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
|
||||||
|
mesh->add_triangle(vi[0], vi[2], vi[3], shader, smooth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
|
||||||
|
|
||||||
nverts.push_back(n);
|
nverts.push_back(n);
|
||||||
}
|
}
|
||||||
@@ -240,7 +249,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
Attribute *attr = mesh->attributes.add(
|
Attribute *attr = mesh->attributes.add(
|
||||||
ustring(l->name().c_str()), TypeDesc::TypeColor, Attribute::CORNER);
|
ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER);
|
||||||
|
|
||||||
BL::MeshColorLayer::data_iterator c;
|
BL::MeshColorLayer::data_iterator c;
|
||||||
float3 *fdata = attr->data_float3();
|
float3 *fdata = attr->data_float3();
|
||||||
@@ -279,7 +288,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
|
|||||||
if(active_render)
|
if(active_render)
|
||||||
attr = mesh->attributes.add(std, name);
|
attr = mesh->attributes.add(std, name);
|
||||||
else
|
else
|
||||||
attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER);
|
attr = mesh->attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
|
||||||
|
|
||||||
BL::MeshTextureFaceLayer::data_iterator t;
|
BL::MeshTextureFaceLayer::data_iterator t;
|
||||||
float3 *fdata = attr->data_float3();
|
float3 *fdata = attr->data_float3();
|
||||||
@@ -319,14 +328,9 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
|
|||||||
* is available in the api. */
|
* is available in the api. */
|
||||||
if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
|
if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
|
||||||
Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED);
|
Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED);
|
||||||
float3 loc = get_float3(b_mesh.texspace_location());
|
|
||||||
float3 size = get_float3(b_mesh.texspace_size());
|
|
||||||
|
|
||||||
if(size.x != 0.0f) size.x = 0.5f/size.x;
|
float3 loc, size;
|
||||||
if(size.y != 0.0f) size.y = 0.5f/size.y;
|
mesh_texture_space(b_mesh, loc, size);
|
||||||
if(size.z != 0.0f) size.z = 0.5f/size.z;
|
|
||||||
|
|
||||||
loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);
|
|
||||||
|
|
||||||
float3 *generated = attr->data_float3();
|
float3 *generated = attr->data_float3();
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
@@ -376,7 +380,7 @@ static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, con
|
|||||||
|
|
||||||
/* Sync */
|
/* Sync */
|
||||||
|
|
||||||
Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated)
|
Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tris)
|
||||||
{
|
{
|
||||||
/* test if we can instance or if the object is modified */
|
/* test if we can instance or if the object is modified */
|
||||||
BL::ID b_ob_data = b_ob.data();
|
BL::ID b_ob_data = b_ob.data();
|
||||||
@@ -435,16 +439,24 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated)
|
|||||||
PointerRNA cmesh = RNA_pointer_get(&b_ob_data.ptr, "cycles");
|
PointerRNA cmesh = RNA_pointer_get(&b_ob_data.ptr, "cycles");
|
||||||
|
|
||||||
vector<Mesh::Triangle> oldtriangle = mesh->triangles;
|
vector<Mesh::Triangle> oldtriangle = mesh->triangles;
|
||||||
|
|
||||||
|
/* compares curve_keys rather than strands in order to handle quick hair adjustsments in dynamic BVH - other methods could probably do this better*/
|
||||||
|
vector<Mesh::CurveKey> oldcurve_keys = mesh->curve_keys;
|
||||||
|
|
||||||
mesh->clear();
|
mesh->clear();
|
||||||
mesh->used_shaders = used_shaders;
|
mesh->used_shaders = used_shaders;
|
||||||
mesh->name = ustring(b_ob_data.name().c_str());
|
mesh->name = ustring(b_ob_data.name().c_str());
|
||||||
|
|
||||||
if(b_mesh) {
|
if(b_mesh) {
|
||||||
if(cmesh.data && experimental && RNA_boolean_get(&cmesh, "use_subdivision"))
|
if(!(hide_tris && experimental && is_cpu)) {
|
||||||
create_subd_mesh(mesh, b_mesh, &cmesh, used_shaders);
|
if(cmesh.data && experimental && RNA_boolean_get(&cmesh, "use_subdivision"))
|
||||||
else
|
create_subd_mesh(mesh, b_mesh, &cmesh, used_shaders);
|
||||||
create_mesh(scene, mesh, b_mesh, used_shaders);
|
else
|
||||||
|
create_mesh(scene, mesh, b_mesh, used_shaders);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(experimental && is_cpu)
|
||||||
|
sync_curves(mesh, b_mesh, b_ob, object_updated);
|
||||||
|
|
||||||
/* free derived mesh */
|
/* free derived mesh */
|
||||||
b_data.meshes.remove(b_mesh);
|
b_data.meshes.remove(b_mesh);
|
||||||
@@ -471,6 +483,13 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated)
|
|||||||
if(memcmp(&oldtriangle[0], &mesh->triangles[0], sizeof(Mesh::Triangle)*oldtriangle.size()) != 0)
|
if(memcmp(&oldtriangle[0], &mesh->triangles[0], sizeof(Mesh::Triangle)*oldtriangle.size()) != 0)
|
||||||
rebuild = true;
|
rebuild = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(oldcurve_keys.size() != mesh->curve_keys.size())
|
||||||
|
rebuild = true;
|
||||||
|
else if(oldcurve_keys.size()) {
|
||||||
|
if(memcmp(&oldcurve_keys[0], &mesh->curve_keys[0], sizeof(Mesh::CurveKey)*oldcurve_keys.size()) != 0)
|
||||||
|
rebuild = true;
|
||||||
|
}
|
||||||
|
|
||||||
mesh->tag_update(scene, rebuild);
|
mesh->tag_update(scene, rebuild);
|
||||||
|
|
||||||
|
@@ -196,7 +196,7 @@ void BlenderSync::sync_background_light()
|
|||||||
|
|
||||||
/* Object */
|
/* Object */
|
||||||
|
|
||||||
Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_ob, Transform& tfm, uint layer_flag, int motion)
|
Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_ob, Transform& tfm, uint layer_flag, int motion, bool hide_tris)
|
||||||
{
|
{
|
||||||
BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent);
|
BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent);
|
||||||
|
|
||||||
@@ -247,7 +247,7 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P
|
|||||||
bool use_holdout = (layer_flag & render_layer.holdout_layer) != 0;
|
bool use_holdout = (layer_flag & render_layer.holdout_layer) != 0;
|
||||||
|
|
||||||
/* mesh sync */
|
/* mesh sync */
|
||||||
object->mesh = sync_mesh(b_ob, object_updated);
|
object->mesh = sync_mesh(b_ob, object_updated, hide_tris);
|
||||||
|
|
||||||
/* sspecial case not tracked by object update flags */
|
/* sspecial case not tracked by object update flags */
|
||||||
if(use_holdout != object->use_holdout) {
|
if(use_holdout != object->use_holdout) {
|
||||||
@@ -390,7 +390,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
|
|||||||
BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_dup->persistent_id();
|
BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_dup->persistent_id();
|
||||||
|
|
||||||
/* sync object and mesh or light data */
|
/* sync object and mesh or light data */
|
||||||
Object *object = sync_object(*b_ob, persistent_id.data, *b_dup, tfm, ob_layer, motion);
|
Object *object = sync_object(*b_ob, persistent_id.data, *b_dup, tfm, ob_layer, motion, false);
|
||||||
|
|
||||||
/* sync possible particle data, note particle_id
|
/* sync possible particle data, note particle_id
|
||||||
* starts counting at 1, first is dummy particle */
|
* starts counting at 1, first is dummy particle */
|
||||||
@@ -412,9 +412,23 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
|
|||||||
/* check if we should render or hide particle emitter */
|
/* check if we should render or hide particle emitter */
|
||||||
BL::Object::particle_systems_iterator b_psys;
|
BL::Object::particle_systems_iterator b_psys;
|
||||||
|
|
||||||
for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys)
|
bool hair_present = false;
|
||||||
if(b_psys->settings().use_render_emitter())
|
bool show_emitter = false;
|
||||||
|
bool hide_tris = false;
|
||||||
|
|
||||||
|
for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) {
|
||||||
|
|
||||||
|
if((b_psys->settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys->settings().type()==BL::ParticleSettings::type_HAIR))
|
||||||
|
hair_present = true;
|
||||||
|
|
||||||
|
if(b_psys->settings().use_render_emitter()) {
|
||||||
hide = false;
|
hide = false;
|
||||||
|
show_emitter = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(hair_present && !show_emitter)
|
||||||
|
hide_tris = true;
|
||||||
|
|
||||||
/* hide original object for duplis */
|
/* hide original object for duplis */
|
||||||
BL::Object parent = b_ob->parent();
|
BL::Object parent = b_ob->parent();
|
||||||
@@ -424,7 +438,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
|
|||||||
if(!hide) {
|
if(!hide) {
|
||||||
/* object itself */
|
/* object itself */
|
||||||
Transform tfm = get_transform(b_ob->matrix_world());
|
Transform tfm = get_transform(b_ob->matrix_world());
|
||||||
sync_object(*b_ob, NULL, PointerRNA_NULL, tfm, ob_layer, motion);
|
sync_object(*b_ob, NULL, PointerRNA_NULL, tfm, ob_layer, motion, hide_tris);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -96,7 +96,7 @@ void BlenderSession::create_session()
|
|||||||
session->set_pause(BlenderSync::get_session_pause(b_scene, background));
|
session->set_pause(BlenderSync::get_session_pause(b_scene, background));
|
||||||
|
|
||||||
/* create sync */
|
/* create sync */
|
||||||
sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
|
sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress, session_params.device.type == DEVICE_CPU);
|
||||||
sync->sync_data(b_v3d, b_engine.camera_override());
|
sync->sync_data(b_v3d, b_engine.camera_override());
|
||||||
|
|
||||||
if(b_rv3d)
|
if(b_rv3d)
|
||||||
@@ -107,6 +107,8 @@ void BlenderSession::create_session()
|
|||||||
/* set buffer parameters */
|
/* set buffer parameters */
|
||||||
BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_v3d, b_rv3d, scene->camera, width, height);
|
BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_v3d, b_rv3d, scene->camera, width, height);
|
||||||
session->reset(buffer_params, session_params.samples);
|
session->reset(buffer_params, session_params.samples);
|
||||||
|
|
||||||
|
b_engine.use_highlight_tiles(session_params.progressive_refine == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_)
|
void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_)
|
||||||
@@ -143,12 +145,14 @@ void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_)
|
|||||||
session->stats.mem_peak = session->stats.mem_used;
|
session->stats.mem_peak = session->stats.mem_used;
|
||||||
|
|
||||||
/* sync object should be re-created */
|
/* sync object should be re-created */
|
||||||
sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
|
sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress, session_params.device.type == DEVICE_CPU);
|
||||||
sync->sync_data(b_v3d, b_engine.camera_override());
|
sync->sync_data(b_v3d, b_engine.camera_override());
|
||||||
sync->sync_camera(b_engine.camera_override(), width, height);
|
sync->sync_camera(b_engine.camera_override(), width, height);
|
||||||
|
|
||||||
BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, PointerRNA_NULL, PointerRNA_NULL, scene->camera, width, height);
|
BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, PointerRNA_NULL, PointerRNA_NULL, scene->camera, width, height);
|
||||||
session->reset(buffer_params, session_params.samples);
|
session->reset(buffer_params, session_params.samples);
|
||||||
|
|
||||||
|
b_engine.use_highlight_tiles(session_params.progressive_refine == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlenderSession::free_session()
|
void BlenderSession::free_session()
|
||||||
@@ -252,7 +256,15 @@ void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_upda
|
|||||||
|
|
||||||
if (do_update_only) {
|
if (do_update_only) {
|
||||||
/* update only needed */
|
/* update only needed */
|
||||||
update_render_result(b_rr, b_rlay, rtile);
|
|
||||||
|
if (rtile.sample != 0) {
|
||||||
|
/* sample would be zero at initial tile update, which is only needed
|
||||||
|
* to tag tile form blender side as IN PROGRESS for proper highlight
|
||||||
|
* no buffers should be sent to blender yet
|
||||||
|
*/
|
||||||
|
update_render_result(b_rr, b_rlay, rtile);
|
||||||
|
}
|
||||||
|
|
||||||
end_render_result(b_engine, b_rr, true);
|
end_render_result(b_engine, b_rr, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@@ -447,6 +447,10 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
|
|||||||
node = new ParticleInfoNode();
|
node = new ParticleInfoNode();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case BL::ShaderNode::type_HAIR_INFO: {
|
||||||
|
node = new HairInfoNode();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case BL::ShaderNode::type_BUMP: {
|
case BL::ShaderNode::type_BUMP: {
|
||||||
node = new BumpNode();
|
node = new BumpNode();
|
||||||
break;
|
break;
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
#include "object.h"
|
#include "object.h"
|
||||||
#include "scene.h"
|
#include "scene.h"
|
||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
|
#include "curves.h"
|
||||||
|
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
|
||||||
@@ -41,7 +42,7 @@ CCL_NAMESPACE_BEGIN
|
|||||||
|
|
||||||
/* Constructor */
|
/* Constructor */
|
||||||
|
|
||||||
BlenderSync::BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::Scene b_scene_, Scene *scene_, bool preview_, Progress &progress_)
|
BlenderSync::BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::Scene b_scene_, Scene *scene_, bool preview_, Progress &progress_, bool is_cpu_)
|
||||||
: b_engine(b_engine_),
|
: b_engine(b_engine_),
|
||||||
b_data(b_data_), b_scene(b_scene_),
|
b_data(b_data_), b_scene(b_scene_),
|
||||||
shader_map(&scene_->shaders),
|
shader_map(&scene_->shaders),
|
||||||
@@ -56,6 +57,7 @@ BlenderSync::BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::
|
|||||||
{
|
{
|
||||||
scene = scene_;
|
scene = scene_;
|
||||||
preview = preview_;
|
preview = preview_;
|
||||||
|
is_cpu = is_cpu_;
|
||||||
}
|
}
|
||||||
|
|
||||||
BlenderSync::~BlenderSync()
|
BlenderSync::~BlenderSync()
|
||||||
@@ -141,6 +143,7 @@ void BlenderSync::sync_data(BL::SpaceView3D b_v3d, BL::Object b_override, const
|
|||||||
sync_integrator();
|
sync_integrator();
|
||||||
sync_film();
|
sync_film();
|
||||||
sync_shaders();
|
sync_shaders();
|
||||||
|
sync_curve_settings();
|
||||||
sync_objects(b_v3d);
|
sync_objects(b_v3d);
|
||||||
sync_motion(b_v3d, b_override);
|
sync_motion(b_v3d, b_override);
|
||||||
}
|
}
|
||||||
|
@@ -50,7 +50,7 @@ class ShaderNode;
|
|||||||
|
|
||||||
class BlenderSync {
|
class BlenderSync {
|
||||||
public:
|
public:
|
||||||
BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data, BL::Scene b_scene, Scene *scene_, bool preview_, Progress &progress_);
|
BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data, BL::Scene b_scene, Scene *scene_, bool preview_, Progress &progress_, bool is_cpu_);
|
||||||
~BlenderSync();
|
~BlenderSync();
|
||||||
|
|
||||||
/* sync */
|
/* sync */
|
||||||
@@ -78,10 +78,12 @@ private:
|
|||||||
void sync_world(bool update_all);
|
void sync_world(bool update_all);
|
||||||
void sync_render_layers(BL::SpaceView3D b_v3d, const char *layer);
|
void sync_render_layers(BL::SpaceView3D b_v3d, const char *layer);
|
||||||
void sync_shaders();
|
void sync_shaders();
|
||||||
|
void sync_curve_settings();
|
||||||
|
|
||||||
void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree);
|
void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree);
|
||||||
Mesh *sync_mesh(BL::Object b_ob, bool object_updated);
|
Mesh *sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tris);
|
||||||
Object *sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_object, Transform& tfm, uint layer_flag, int motion);
|
void sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool object_updated);
|
||||||
|
Object *sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_object, Transform& tfm, uint layer_flag, int motion, bool hide_tris);
|
||||||
void sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm);
|
void sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm);
|
||||||
void sync_background_light();
|
void sync_background_light();
|
||||||
void sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion);
|
void sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion);
|
||||||
@@ -113,6 +115,7 @@ private:
|
|||||||
Scene *scene;
|
Scene *scene;
|
||||||
bool preview;
|
bool preview;
|
||||||
bool experimental;
|
bool experimental;
|
||||||
|
bool is_cpu;
|
||||||
|
|
||||||
struct RenderLayerInfo {
|
struct RenderLayerInfo {
|
||||||
RenderLayerInfo()
|
RenderLayerInfo()
|
||||||
|
@@ -242,6 +242,20 @@ static inline string blender_absolute_path(BL::BlendData b_data, BL::ID b_id, co
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Texture Space */
|
||||||
|
|
||||||
|
static inline void mesh_texture_space(BL::Mesh b_mesh, float3& loc, float3& size)
|
||||||
|
{
|
||||||
|
loc = get_float3(b_mesh.texspace_location());
|
||||||
|
size = get_float3(b_mesh.texspace_size());
|
||||||
|
|
||||||
|
if(size.x != 0.0f) size.x = 0.5f/size.x;
|
||||||
|
if(size.y != 0.0f) size.y = 0.5f/size.y;
|
||||||
|
if(size.z != 0.0f) size.z = 0.5f/size.z;
|
||||||
|
|
||||||
|
loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
/* ID Map
|
/* ID Map
|
||||||
*
|
*
|
||||||
* Utility class to keep in sync with blender data.
|
* Utility class to keep in sync with blender data.
|
||||||
|
@@ -75,6 +75,8 @@ bool BVH::cache_read(CacheData& key)
|
|||||||
foreach(Object *ob, objects) {
|
foreach(Object *ob, objects) {
|
||||||
key.add(ob->mesh->verts);
|
key.add(ob->mesh->verts);
|
||||||
key.add(ob->mesh->triangles);
|
key.add(ob->mesh->triangles);
|
||||||
|
key.add(ob->mesh->curve_keys);
|
||||||
|
key.add(ob->mesh->curves);
|
||||||
key.add(&ob->bounds, sizeof(ob->bounds));
|
key.add(&ob->bounds, sizeof(ob->bounds));
|
||||||
key.add(&ob->visibility, sizeof(ob->visibility));
|
key.add(&ob->visibility, sizeof(ob->visibility));
|
||||||
key.add(&ob->mesh->transform_applied, sizeof(bool));
|
key.add(&ob->mesh->transform_applied, sizeof(bool));
|
||||||
@@ -91,6 +93,7 @@ bool BVH::cache_read(CacheData& key)
|
|||||||
value.read(pack.nodes);
|
value.read(pack.nodes);
|
||||||
value.read(pack.object_node);
|
value.read(pack.object_node);
|
||||||
value.read(pack.tri_woop);
|
value.read(pack.tri_woop);
|
||||||
|
value.read(pack.prim_segment);
|
||||||
value.read(pack.prim_visibility);
|
value.read(pack.prim_visibility);
|
||||||
value.read(pack.prim_index);
|
value.read(pack.prim_index);
|
||||||
value.read(pack.prim_object);
|
value.read(pack.prim_object);
|
||||||
@@ -112,6 +115,7 @@ void BVH::cache_write(CacheData& key)
|
|||||||
value.add(pack.nodes);
|
value.add(pack.nodes);
|
||||||
value.add(pack.object_node);
|
value.add(pack.object_node);
|
||||||
value.add(pack.tri_woop);
|
value.add(pack.tri_woop);
|
||||||
|
value.add(pack.prim_segment);
|
||||||
value.add(pack.prim_visibility);
|
value.add(pack.prim_visibility);
|
||||||
value.add(pack.prim_index);
|
value.add(pack.prim_index);
|
||||||
value.add(pack.prim_object);
|
value.add(pack.prim_object);
|
||||||
@@ -157,10 +161,11 @@ void BVH::build(Progress& progress)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* build nodes */
|
/* build nodes */
|
||||||
|
vector<int> prim_segment;
|
||||||
vector<int> prim_index;
|
vector<int> prim_index;
|
||||||
vector<int> prim_object;
|
vector<int> prim_object;
|
||||||
|
|
||||||
BVHBuild bvh_build(objects, prim_index, prim_object, params, progress);
|
BVHBuild bvh_build(objects, prim_segment, prim_index, prim_object, params, progress);
|
||||||
BVHNode *root = bvh_build.run();
|
BVHNode *root = bvh_build.run();
|
||||||
|
|
||||||
if(progress.get_cancel()) {
|
if(progress.get_cancel()) {
|
||||||
@@ -169,6 +174,7 @@ void BVH::build(Progress& progress)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* todo: get rid of this copy */
|
/* todo: get rid of this copy */
|
||||||
|
pack.prim_segment = prim_segment;
|
||||||
pack.prim_index = prim_index;
|
pack.prim_index = prim_index;
|
||||||
pack.prim_object = prim_object;
|
pack.prim_object = prim_object;
|
||||||
|
|
||||||
@@ -182,8 +188,8 @@ void BVH::build(Progress& progress)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* pack triangles */
|
/* pack triangles */
|
||||||
progress.set_substatus("Packing BVH triangles");
|
progress.set_substatus("Packing BVH triangles and strands");
|
||||||
pack_triangles();
|
pack_primitives();
|
||||||
|
|
||||||
if(progress.get_cancel()) {
|
if(progress.get_cancel()) {
|
||||||
root->deleteSubtree();
|
root->deleteSubtree();
|
||||||
@@ -215,8 +221,8 @@ void BVH::build(Progress& progress)
|
|||||||
|
|
||||||
void BVH::refit(Progress& progress)
|
void BVH::refit(Progress& progress)
|
||||||
{
|
{
|
||||||
progress.set_substatus("Packing BVH triangles");
|
progress.set_substatus("Packing BVH primitives");
|
||||||
pack_triangles();
|
pack_primitives();
|
||||||
|
|
||||||
if(progress.get_cancel()) return;
|
if(progress.get_cancel()) return;
|
||||||
|
|
||||||
@@ -263,7 +269,52 @@ void BVH::pack_triangle(int idx, float4 woop[3])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BVH::pack_triangles()
|
/* Curves*/
|
||||||
|
|
||||||
|
void BVH::pack_curve_segment(int idx, float4 woop[3])
|
||||||
|
{
|
||||||
|
int tob = pack.prim_object[idx];
|
||||||
|
const Mesh *mesh = objects[tob]->mesh;
|
||||||
|
int tidx = pack.prim_index[idx];
|
||||||
|
int segment = pack.prim_segment[idx];
|
||||||
|
int k0 = mesh->curves[tidx].first_key + segment;
|
||||||
|
int k1 = mesh->curves[tidx].first_key + segment + 1;
|
||||||
|
float3 v0 = mesh->curve_keys[k0].co;
|
||||||
|
float3 v1 = mesh->curve_keys[k1].co;
|
||||||
|
|
||||||
|
float3 d0 = v1 - v0;
|
||||||
|
float l = len(d0);
|
||||||
|
|
||||||
|
/*Plan
|
||||||
|
*Transform tfm = make_transform(
|
||||||
|
* location <3> , l,
|
||||||
|
* extra curve data <3> , StrID,
|
||||||
|
* nextkey, flags/tip?, 0, 0);
|
||||||
|
*/
|
||||||
|
Attribute *attr_tangent = mesh->curve_attributes.find(ATTR_STD_CURVE_TANGENT);
|
||||||
|
float3 tg0 = make_float3(1.0f, 0.0f, 0.0f);
|
||||||
|
float3 tg1 = make_float3(1.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
if(attr_tangent) {
|
||||||
|
const float3 *data_tangent = attr_tangent->data_float3();
|
||||||
|
|
||||||
|
tg0 = data_tangent[k0];
|
||||||
|
tg1 = data_tangent[k1];
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform tfm = make_transform(
|
||||||
|
tg0.x, tg0.y, tg0.z, l,
|
||||||
|
tg1.x, tg1.y, tg1.z, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 1);
|
||||||
|
|
||||||
|
woop[0] = tfm.x;
|
||||||
|
woop[1] = tfm.y;
|
||||||
|
woop[2] = tfm.z;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void BVH::pack_primitives()
|
||||||
{
|
{
|
||||||
int nsize = TRI_NODE_SIZE;
|
int nsize = TRI_NODE_SIZE;
|
||||||
size_t tidx_size = pack.prim_index.size();
|
size_t tidx_size = pack.prim_index.size();
|
||||||
@@ -277,7 +328,11 @@ void BVH::pack_triangles()
|
|||||||
if(pack.prim_index[i] != -1) {
|
if(pack.prim_index[i] != -1) {
|
||||||
float4 woop[3];
|
float4 woop[3];
|
||||||
|
|
||||||
pack_triangle(i, woop);
|
if(pack.prim_segment[i] != ~0)
|
||||||
|
pack_curve_segment(i, woop);
|
||||||
|
else
|
||||||
|
pack_triangle(i, woop);
|
||||||
|
|
||||||
memcpy(&pack.tri_woop[i * nsize], woop, sizeof(float4)*3);
|
memcpy(&pack.tri_woop[i * nsize], woop, sizeof(float4)*3);
|
||||||
|
|
||||||
int tob = pack.prim_object[i];
|
int tob = pack.prim_object[i];
|
||||||
@@ -300,11 +355,15 @@ void BVH::pack_instances(size_t nodes_size)
|
|||||||
/* adjust primitive index to point to the triangle in the global array, for
|
/* adjust primitive index to point to the triangle in the global array, for
|
||||||
* meshes with transform applied and already in the top level BVH */
|
* meshes with transform applied and already in the top level BVH */
|
||||||
for(size_t i = 0; i < pack.prim_index.size(); i++)
|
for(size_t i = 0; i < pack.prim_index.size(); i++)
|
||||||
if(pack.prim_index[i] != -1)
|
if(pack.prim_index[i] != -1) {
|
||||||
pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset;
|
if(pack.prim_segment[i] != ~0)
|
||||||
|
pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curve_offset;
|
||||||
|
else
|
||||||
|
pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset;
|
||||||
|
}
|
||||||
|
|
||||||
/* track offsets of instanced BVH data in global array */
|
/* track offsets of instanced BVH data in global array */
|
||||||
size_t tri_offset = pack.prim_index.size();
|
size_t prim_offset = pack.prim_index.size();
|
||||||
size_t nodes_offset = nodes_size;
|
size_t nodes_offset = nodes_size;
|
||||||
|
|
||||||
/* clear array that gives the node indexes for instanced objects */
|
/* clear array that gives the node indexes for instanced objects */
|
||||||
@@ -339,6 +398,7 @@ void BVH::pack_instances(size_t nodes_size)
|
|||||||
mesh_map.clear();
|
mesh_map.clear();
|
||||||
|
|
||||||
pack.prim_index.resize(prim_index_size);
|
pack.prim_index.resize(prim_index_size);
|
||||||
|
pack.prim_segment.resize(prim_index_size);
|
||||||
pack.prim_object.resize(prim_index_size);
|
pack.prim_object.resize(prim_index_size);
|
||||||
pack.prim_visibility.resize(prim_index_size);
|
pack.prim_visibility.resize(prim_index_size);
|
||||||
pack.tri_woop.resize(tri_woop_size);
|
pack.tri_woop.resize(tri_woop_size);
|
||||||
@@ -346,6 +406,7 @@ void BVH::pack_instances(size_t nodes_size)
|
|||||||
pack.object_node.resize(objects.size());
|
pack.object_node.resize(objects.size());
|
||||||
|
|
||||||
int *pack_prim_index = (pack.prim_index.size())? &pack.prim_index[0]: NULL;
|
int *pack_prim_index = (pack.prim_index.size())? &pack.prim_index[0]: NULL;
|
||||||
|
int *pack_prim_segment = (pack.prim_segment.size())? &pack.prim_segment[0]: NULL;
|
||||||
int *pack_prim_object = (pack.prim_object.size())? &pack.prim_object[0]: NULL;
|
int *pack_prim_object = (pack.prim_object.size())? &pack.prim_object[0]: NULL;
|
||||||
uint *pack_prim_visibility = (pack.prim_visibility.size())? &pack.prim_visibility[0]: NULL;
|
uint *pack_prim_visibility = (pack.prim_visibility.size())? &pack.prim_visibility[0]: NULL;
|
||||||
float4 *pack_tri_woop = (pack.tri_woop.size())? &pack.tri_woop[0]: NULL;
|
float4 *pack_tri_woop = (pack.tri_woop.size())? &pack.tri_woop[0]: NULL;
|
||||||
@@ -376,6 +437,7 @@ void BVH::pack_instances(size_t nodes_size)
|
|||||||
|
|
||||||
int noffset = nodes_offset/nsize;
|
int noffset = nodes_offset/nsize;
|
||||||
int mesh_tri_offset = mesh->tri_offset;
|
int mesh_tri_offset = mesh->tri_offset;
|
||||||
|
int mesh_curve_offset = mesh->curve_offset;
|
||||||
|
|
||||||
/* fill in node indexes for instances */
|
/* fill in node indexes for instances */
|
||||||
if((bvh->pack.is_leaf.size() != 0) && bvh->pack.is_leaf[0])
|
if((bvh->pack.is_leaf.size() != 0) && bvh->pack.is_leaf[0])
|
||||||
@@ -389,10 +451,16 @@ void BVH::pack_instances(size_t nodes_size)
|
|||||||
if(bvh->pack.prim_index.size()) {
|
if(bvh->pack.prim_index.size()) {
|
||||||
size_t bvh_prim_index_size = bvh->pack.prim_index.size();
|
size_t bvh_prim_index_size = bvh->pack.prim_index.size();
|
||||||
int *bvh_prim_index = &bvh->pack.prim_index[0];
|
int *bvh_prim_index = &bvh->pack.prim_index[0];
|
||||||
|
int *bvh_prim_segment = &bvh->pack.prim_segment[0];
|
||||||
uint *bvh_prim_visibility = &bvh->pack.prim_visibility[0];
|
uint *bvh_prim_visibility = &bvh->pack.prim_visibility[0];
|
||||||
|
|
||||||
for(size_t i = 0; i < bvh_prim_index_size; i++) {
|
for(size_t i = 0; i < bvh_prim_index_size; i++) {
|
||||||
pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset;
|
if(bvh->pack.prim_segment[i] != ~0)
|
||||||
|
pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_curve_offset;
|
||||||
|
else
|
||||||
|
pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset;
|
||||||
|
|
||||||
|
pack_prim_segment[pack_prim_index_offset] = bvh_prim_segment[i];
|
||||||
pack_prim_visibility[pack_prim_index_offset] = bvh_prim_visibility[i];
|
pack_prim_visibility[pack_prim_index_offset] = bvh_prim_visibility[i];
|
||||||
pack_prim_object[pack_prim_index_offset] = 0; // unused for instances
|
pack_prim_object[pack_prim_index_offset] = 0; // unused for instances
|
||||||
pack_prim_index_offset++;
|
pack_prim_index_offset++;
|
||||||
@@ -401,7 +469,7 @@ void BVH::pack_instances(size_t nodes_size)
|
|||||||
|
|
||||||
/* merge triangle intersection data */
|
/* merge triangle intersection data */
|
||||||
if(bvh->pack.tri_woop.size()) {
|
if(bvh->pack.tri_woop.size()) {
|
||||||
memcpy(pack_tri_woop+pack_tri_woop_offset, &bvh->pack.tri_woop[0],
|
memcpy(pack_tri_woop + pack_tri_woop_offset, &bvh->pack.tri_woop[0],
|
||||||
bvh->pack.tri_woop.size()*sizeof(float4));
|
bvh->pack.tri_woop.size()*sizeof(float4));
|
||||||
pack_tri_woop_offset += bvh->pack.tri_woop.size();
|
pack_tri_woop_offset += bvh->pack.tri_woop.size();
|
||||||
}
|
}
|
||||||
@@ -420,8 +488,8 @@ void BVH::pack_instances(size_t nodes_size)
|
|||||||
int4 data = bvh_nodes[i + nsize_bbox];
|
int4 data = bvh_nodes[i + nsize_bbox];
|
||||||
|
|
||||||
if(bvh_is_leaf && bvh_is_leaf[j]) {
|
if(bvh_is_leaf && bvh_is_leaf[j]) {
|
||||||
data.x += tri_offset;
|
data.x += prim_offset;
|
||||||
data.y += tri_offset;
|
data.y += prim_offset;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
data.x += (data.x < 0)? -noffset: noffset;
|
data.x += (data.x < 0)? -noffset: noffset;
|
||||||
@@ -443,7 +511,7 @@ void BVH::pack_instances(size_t nodes_size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nodes_offset += bvh->pack.nodes.size();
|
nodes_offset += bvh->pack.nodes.size();
|
||||||
tri_offset += bvh->pack.prim_index.size();
|
prim_offset += bvh->pack.prim_index.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -544,25 +612,38 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
|
|||||||
|
|
||||||
if(leaf) {
|
if(leaf) {
|
||||||
/* refit leaf node */
|
/* refit leaf node */
|
||||||
for(int tri = c0; tri < c1; tri++) {
|
for(int prim = c0; prim < c1; prim++) {
|
||||||
int tidx = pack.prim_index[tri];
|
int pidx = pack.prim_index[prim];
|
||||||
int tob = pack.prim_object[tri];
|
int tob = pack.prim_object[prim];
|
||||||
Object *ob = objects[tob];
|
Object *ob = objects[tob];
|
||||||
|
|
||||||
if(tidx == -1) {
|
if(pidx == -1) {
|
||||||
/* object instance */
|
/* object instance */
|
||||||
bbox.grow(ob->bounds);
|
bbox.grow(ob->bounds);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* triangles */
|
/* primitives */
|
||||||
const Mesh *mesh = ob->mesh;
|
const Mesh *mesh = ob->mesh;
|
||||||
int tri_offset = (params.top_level)? mesh->tri_offset: 0;
|
|
||||||
const int *vidx = mesh->triangles[tidx - tri_offset].v;
|
|
||||||
const float3 *vpos = &mesh->verts[0];
|
|
||||||
|
|
||||||
bbox.grow(vpos[vidx[0]]);
|
if(pack.prim_segment[prim] != ~0) {
|
||||||
bbox.grow(vpos[vidx[1]]);
|
/* curves */
|
||||||
bbox.grow(vpos[vidx[2]]);
|
int str_offset = (params.top_level)? mesh->curve_offset: 0;
|
||||||
|
int k0 = mesh->curves[pidx - str_offset].first_key + pack.prim_segment[prim]; // XXX!
|
||||||
|
int k1 = k0 + 1;
|
||||||
|
|
||||||
|
bbox.grow(mesh->curve_keys[k0].co, mesh->curve_keys[k0].radius);
|
||||||
|
bbox.grow(mesh->curve_keys[k1].co, mesh->curve_keys[k1].radius);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* triangles */
|
||||||
|
int tri_offset = (params.top_level)? mesh->tri_offset: 0;
|
||||||
|
const int *vidx = mesh->triangles[pidx - tri_offset].v;
|
||||||
|
const float3 *vpos = &mesh->verts[0];
|
||||||
|
|
||||||
|
bbox.grow(vpos[vidx[0]]);
|
||||||
|
bbox.grow(vpos[vidx[1]]);
|
||||||
|
bbox.grow(vpos[vidx[2]]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
visibility |= ob->visibility;
|
visibility |= ob->visibility;
|
||||||
|
@@ -51,7 +51,9 @@ struct PackedBVH {
|
|||||||
/* object index to BVH node index mapping for instances */
|
/* object index to BVH node index mapping for instances */
|
||||||
array<int> object_node;
|
array<int> object_node;
|
||||||
/* precomputed triangle intersection data, one triangle is 4x float4 */
|
/* precomputed triangle intersection data, one triangle is 4x float4 */
|
||||||
array<float4> tri_woop;
|
array<float4> tri_woop;
|
||||||
|
/* primitive type - triangle or strand (should be moved to flag?) */
|
||||||
|
array<int> prim_segment;
|
||||||
/* visibility visibilitys for primitives */
|
/* visibility visibilitys for primitives */
|
||||||
array<uint> prim_visibility;
|
array<uint> prim_visibility;
|
||||||
/* mapping from BVH primitive index to true primitive index, as primitives
|
/* mapping from BVH primitive index to true primitive index, as primitives
|
||||||
@@ -101,9 +103,10 @@ protected:
|
|||||||
bool cache_read(CacheData& key);
|
bool cache_read(CacheData& key);
|
||||||
void cache_write(CacheData& key);
|
void cache_write(CacheData& key);
|
||||||
|
|
||||||
/* triangles */
|
/* triangles and strands*/
|
||||||
void pack_triangles();
|
void pack_primitives();
|
||||||
void pack_triangle(int idx, float4 woop[3]);
|
void pack_triangle(int idx, float4 woop[3]);
|
||||||
|
void pack_curve_segment(int idx, float4 woop[3]);
|
||||||
|
|
||||||
/* merge instance BVH's */
|
/* merge instance BVH's */
|
||||||
void pack_instances(size_t nodes_size);
|
void pack_instances(size_t nodes_size);
|
||||||
|
@@ -48,9 +48,10 @@ public:
|
|||||||
/* Constructor / Destructor */
|
/* Constructor / Destructor */
|
||||||
|
|
||||||
BVHBuild::BVHBuild(const vector<Object*>& objects_,
|
BVHBuild::BVHBuild(const vector<Object*>& objects_,
|
||||||
vector<int>& prim_index_, vector<int>& prim_object_,
|
vector<int>& prim_segment_, vector<int>& prim_index_, vector<int>& prim_object_,
|
||||||
const BVHParams& params_, Progress& progress_)
|
const BVHParams& params_, Progress& progress_)
|
||||||
: objects(objects_),
|
: objects(objects_),
|
||||||
|
prim_segment(prim_segment_),
|
||||||
prim_index(prim_index_),
|
prim_index(prim_index_),
|
||||||
prim_object(prim_object_),
|
prim_object(prim_object_),
|
||||||
params(params_),
|
params(params_),
|
||||||
@@ -73,25 +74,55 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
|
|||||||
BoundBox bounds = BoundBox::empty;
|
BoundBox bounds = BoundBox::empty;
|
||||||
|
|
||||||
for(int k = 0; k < 3; k++) {
|
for(int k = 0; k < 3; k++) {
|
||||||
float3 pt = mesh->verts[t.v[k]];
|
float3 co = mesh->verts[t.v[k]];
|
||||||
bounds.grow(pt);
|
bounds.grow(co);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bounds.valid()) {
|
if(bounds.valid()) {
|
||||||
references.push_back(BVHReference(bounds, j, i));
|
references.push_back(BVHReference(bounds, j, i, ~0));
|
||||||
root.grow(bounds);
|
root.grow(bounds);
|
||||||
center.grow(bounds.center2());
|
center.grow(bounds.center2());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(uint j = 0; j < mesh->curves.size(); j++) {
|
||||||
|
Mesh::Curve curve = mesh->curves[j];
|
||||||
|
|
||||||
|
for(int k = 0; k < curve.num_keys - 1; k++) {
|
||||||
|
BoundBox bounds = BoundBox::empty;
|
||||||
|
|
||||||
|
float3 co0 = mesh->curve_keys[curve.first_key + k].co;
|
||||||
|
float3 co1 = mesh->curve_keys[curve.first_key + k + 1].co;
|
||||||
|
|
||||||
|
bounds.grow(co0, mesh->curve_keys[curve.first_key + k].radius);
|
||||||
|
bounds.grow(co1, mesh->curve_keys[curve.first_key + k + 1].radius);
|
||||||
|
|
||||||
|
if(bounds.valid()) {
|
||||||
|
references.push_back(BVHReference(bounds, j, i, k));
|
||||||
|
root.grow(bounds);
|
||||||
|
center.grow(bounds.center2());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BVHBuild::add_reference_object(BoundBox& root, BoundBox& center, Object *ob, int i)
|
void BVHBuild::add_reference_object(BoundBox& root, BoundBox& center, Object *ob, int i)
|
||||||
{
|
{
|
||||||
references.push_back(BVHReference(ob->bounds, -1, i));
|
references.push_back(BVHReference(ob->bounds, -1, i, false));
|
||||||
root.grow(ob->bounds);
|
root.grow(ob->bounds);
|
||||||
center.grow(ob->bounds.center2());
|
center.grow(ob->bounds.center2());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t count_curve_segments(Mesh *mesh)
|
||||||
|
{
|
||||||
|
size_t num = 0, num_curves = mesh->curves.size();
|
||||||
|
|
||||||
|
for(size_t i = 0; i < num_curves; i++)
|
||||||
|
num += mesh->curves[i].num_keys - 1;
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
void BVHBuild::add_references(BVHRange& root)
|
void BVHBuild::add_references(BVHRange& root)
|
||||||
{
|
{
|
||||||
/* reserve space for references */
|
/* reserve space for references */
|
||||||
@@ -99,13 +130,17 @@ void BVHBuild::add_references(BVHRange& root)
|
|||||||
|
|
||||||
foreach(Object *ob, objects) {
|
foreach(Object *ob, objects) {
|
||||||
if(params.top_level) {
|
if(params.top_level) {
|
||||||
if(ob->mesh->transform_applied)
|
if(ob->mesh->transform_applied) {
|
||||||
num_alloc_references += ob->mesh->triangles.size();
|
num_alloc_references += ob->mesh->triangles.size();
|
||||||
|
num_alloc_references += count_curve_segments(ob->mesh);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
num_alloc_references++;
|
num_alloc_references++;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
num_alloc_references += ob->mesh->triangles.size();
|
num_alloc_references += ob->mesh->triangles.size();
|
||||||
|
num_alloc_references += count_curve_segments(ob->mesh);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
references.reserve(num_alloc_references);
|
references.reserve(num_alloc_references);
|
||||||
@@ -162,6 +197,7 @@ BVHNode* BVHBuild::run()
|
|||||||
progress_total = references.size();
|
progress_total = references.size();
|
||||||
progress_original_total = progress_total;
|
progress_original_total = progress_total;
|
||||||
|
|
||||||
|
prim_segment.resize(references.size());
|
||||||
prim_index.resize(references.size());
|
prim_index.resize(references.size());
|
||||||
prim_object.resize(references.size());
|
prim_object.resize(references.size());
|
||||||
|
|
||||||
@@ -319,10 +355,12 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
|
|||||||
if(start == prim_index.size()) {
|
if(start == prim_index.size()) {
|
||||||
assert(params.use_spatial_split);
|
assert(params.use_spatial_split);
|
||||||
|
|
||||||
|
prim_segment.push_back(ref->prim_segment());
|
||||||
prim_index.push_back(ref->prim_index());
|
prim_index.push_back(ref->prim_index());
|
||||||
prim_object.push_back(ref->prim_object());
|
prim_object.push_back(ref->prim_object());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
prim_segment[start] = ref->prim_segment();
|
||||||
prim_index[start] = ref->prim_index();
|
prim_index[start] = ref->prim_index();
|
||||||
prim_object[start] = ref->prim_object();
|
prim_object[start] = ref->prim_object();
|
||||||
}
|
}
|
||||||
@@ -345,6 +383,7 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
|
|||||||
|
|
||||||
BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
|
BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
|
||||||
{
|
{
|
||||||
|
vector<int>& p_segment = prim_segment;
|
||||||
vector<int>& p_index = prim_index;
|
vector<int>& p_index = prim_index;
|
||||||
vector<int>& p_object = prim_object;
|
vector<int>& p_object = prim_object;
|
||||||
BoundBox bounds = BoundBox::empty;
|
BoundBox bounds = BoundBox::empty;
|
||||||
@@ -358,10 +397,12 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
|
|||||||
if(range.start() + num == prim_index.size()) {
|
if(range.start() + num == prim_index.size()) {
|
||||||
assert(params.use_spatial_split);
|
assert(params.use_spatial_split);
|
||||||
|
|
||||||
|
p_segment.push_back(ref.prim_segment());
|
||||||
p_index.push_back(ref.prim_index());
|
p_index.push_back(ref.prim_index());
|
||||||
p_object.push_back(ref.prim_object());
|
p_object.push_back(ref.prim_object());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
p_segment[range.start() + num] = ref.prim_segment();
|
||||||
p_index[range.start() + num] = ref.prim_index();
|
p_index[range.start() + num] = ref.prim_index();
|
||||||
p_object[range.start() + num] = ref.prim_object();
|
p_object[range.start() + num] = ref.prim_object();
|
||||||
}
|
}
|
||||||
|
@@ -44,6 +44,7 @@ public:
|
|||||||
/* Constructor/Destructor */
|
/* Constructor/Destructor */
|
||||||
BVHBuild(
|
BVHBuild(
|
||||||
const vector<Object*>& objects,
|
const vector<Object*>& objects,
|
||||||
|
vector<int>& prim_segment,
|
||||||
vector<int>& prim_index,
|
vector<int>& prim_index,
|
||||||
vector<int>& prim_object,
|
vector<int>& prim_object,
|
||||||
const BVHParams& params,
|
const BVHParams& params,
|
||||||
@@ -87,6 +88,7 @@ protected:
|
|||||||
int num_original_references;
|
int num_original_references;
|
||||||
|
|
||||||
/* output primitive indexes and objects */
|
/* output primitive indexes and objects */
|
||||||
|
vector<int>& prim_segment;
|
||||||
vector<int>& prim_index;
|
vector<int>& prim_index;
|
||||||
vector<int>& prim_object;
|
vector<int>& prim_object;
|
||||||
|
|
||||||
|
@@ -98,19 +98,22 @@ class BVHReference
|
|||||||
public:
|
public:
|
||||||
__forceinline BVHReference() {}
|
__forceinline BVHReference() {}
|
||||||
|
|
||||||
__forceinline BVHReference(const BoundBox& bounds_, int prim_index_, int prim_object_)
|
__forceinline BVHReference(const BoundBox& bounds_, int prim_index_, int prim_object_, int prim_segment)
|
||||||
: rbounds(bounds_)
|
: rbounds(bounds_)
|
||||||
{
|
{
|
||||||
rbounds.min.w = __int_as_float(prim_index_);
|
rbounds.min.w = __int_as_float(prim_index_);
|
||||||
rbounds.max.w = __int_as_float(prim_object_);
|
rbounds.max.w = __int_as_float(prim_object_);
|
||||||
|
segment = prim_segment;
|
||||||
}
|
}
|
||||||
|
|
||||||
__forceinline const BoundBox& bounds() const { return rbounds; }
|
__forceinline const BoundBox& bounds() const { return rbounds; }
|
||||||
__forceinline int prim_index() const { return __float_as_int(rbounds.min.w); }
|
__forceinline int prim_index() const { return __float_as_int(rbounds.min.w); }
|
||||||
__forceinline int prim_object() const { return __float_as_int(rbounds.max.w); }
|
__forceinline int prim_object() const { return __float_as_int(rbounds.max.w); }
|
||||||
|
__forceinline int prim_segment() const { return segment; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BoundBox rbounds;
|
BoundBox rbounds;
|
||||||
|
uint segment;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* BVH Range
|
/* BVH Range
|
||||||
|
@@ -43,6 +43,8 @@ public:
|
|||||||
else if(ra.prim_object() > rb.prim_object()) return false;
|
else if(ra.prim_object() > rb.prim_object()) return false;
|
||||||
else if(ra.prim_index() < rb.prim_index()) return true;
|
else if(ra.prim_index() < rb.prim_index()) return true;
|
||||||
else if(ra.prim_index() > rb.prim_index()) return false;
|
else if(ra.prim_index() > rb.prim_index()) return false;
|
||||||
|
else if(ra.prim_segment() < rb.prim_segment()) return true;
|
||||||
|
else if(ra.prim_segment() > rb.prim_segment()) return false;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -252,14 +252,41 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH
|
|||||||
/* loop over vertices/edges. */
|
/* loop over vertices/edges. */
|
||||||
Object *ob = builder->objects[ref.prim_object()];
|
Object *ob = builder->objects[ref.prim_object()];
|
||||||
const Mesh *mesh = ob->mesh;
|
const Mesh *mesh = ob->mesh;
|
||||||
const int *inds = mesh->triangles[ref.prim_index()].v;
|
|
||||||
const float3 *verts = &mesh->verts[0];
|
|
||||||
const float3* v1 = &verts[inds[2]];
|
|
||||||
|
|
||||||
for(int i = 0; i < 3; i++) {
|
if (ref.prim_segment() == ~0) {
|
||||||
const float3* v0 = v1;
|
const int *inds = mesh->triangles[ref.prim_index()].v;
|
||||||
int vindex = inds[i];
|
const float3 *verts = &mesh->verts[0];
|
||||||
v1 = &verts[vindex];
|
const float3* v1 = &verts[inds[2]];
|
||||||
|
|
||||||
|
for(int i = 0; i < 3; i++) {
|
||||||
|
const float3* v0 = v1;
|
||||||
|
int vindex = inds[i];
|
||||||
|
v1 = &verts[vindex];
|
||||||
|
float v0p = (*v0)[dim];
|
||||||
|
float v1p = (*v1)[dim];
|
||||||
|
|
||||||
|
/* insert vertex to the boxes it belongs to. */
|
||||||
|
if(v0p <= pos)
|
||||||
|
left_bounds.grow(*v0);
|
||||||
|
|
||||||
|
if(v0p >= pos)
|
||||||
|
right_bounds.grow(*v0);
|
||||||
|
|
||||||
|
/* edge intersects the plane => insert intersection to both boxes. */
|
||||||
|
if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) {
|
||||||
|
float3 t = lerp(*v0, *v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f));
|
||||||
|
left_bounds.grow(t);
|
||||||
|
right_bounds.grow(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* curve split: NOTE - Currently ignores curve width and needs to be fixed.*/
|
||||||
|
const int k0 = mesh->curves[ref.prim_index()].first_key + ref.prim_segment();
|
||||||
|
const int k1 = k0 + 1;
|
||||||
|
const float3* v0 = &mesh->curve_keys[k0].co;
|
||||||
|
const float3* v1 = &mesh->curve_keys[k1].co;
|
||||||
|
|
||||||
float v0p = (*v0)[dim];
|
float v0p = (*v0)[dim];
|
||||||
float v1p = (*v1)[dim];
|
float v1p = (*v1)[dim];
|
||||||
|
|
||||||
@@ -270,6 +297,12 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH
|
|||||||
if(v0p >= pos)
|
if(v0p >= pos)
|
||||||
right_bounds.grow(*v0);
|
right_bounds.grow(*v0);
|
||||||
|
|
||||||
|
if(v1p <= pos)
|
||||||
|
left_bounds.grow(*v1);
|
||||||
|
|
||||||
|
if(v1p >= pos)
|
||||||
|
right_bounds.grow(*v1);
|
||||||
|
|
||||||
/* edge intersects the plane => insert intersection to both boxes. */
|
/* edge intersects the plane => insert intersection to both boxes. */
|
||||||
if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) {
|
if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) {
|
||||||
float3 t = lerp(*v0, *v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f));
|
float3 t = lerp(*v0, *v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f));
|
||||||
@@ -284,9 +317,9 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH
|
|||||||
left_bounds.intersect(ref.bounds());
|
left_bounds.intersect(ref.bounds());
|
||||||
right_bounds.intersect(ref.bounds());
|
right_bounds.intersect(ref.bounds());
|
||||||
|
|
||||||
/* set referecnes */
|
/* set references */
|
||||||
left = BVHReference(left_bounds, ref.prim_index(), ref.prim_object());
|
left = BVHReference(left_bounds, ref.prim_index(), ref.prim_object(), ref.prim_segment());
|
||||||
right = BVHReference(right_bounds, ref.prim_index(), ref.prim_object());
|
right = BVHReference(right_bounds, ref.prim_index(), ref.prim_object(), ref.prim_segment());
|
||||||
}
|
}
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
@@ -84,6 +84,7 @@ public:
|
|||||||
/* info */
|
/* info */
|
||||||
DeviceInfo info;
|
DeviceInfo info;
|
||||||
virtual const string& error_message() { return error_msg; }
|
virtual const string& error_message() { return error_msg; }
|
||||||
|
bool have_error() { return !error_message().empty(); }
|
||||||
|
|
||||||
/* statistics */
|
/* statistics */
|
||||||
Stats &stats;
|
Stats &stats;
|
||||||
|
@@ -124,7 +124,7 @@ public:
|
|||||||
if(error_msg == "") \
|
if(error_msg == "") \
|
||||||
error_msg = message; \
|
error_msg = message; \
|
||||||
fprintf(stderr, "%s\n", message.c_str()); \
|
fprintf(stderr, "%s\n", message.c_str()); \
|
||||||
cuda_abort(); \
|
/*cuda_abort();*/ \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,7 +326,8 @@ public:
|
|||||||
void mem_copy_to(device_memory& mem)
|
void mem_copy_to(device_memory& mem)
|
||||||
{
|
{
|
||||||
cuda_push_context();
|
cuda_push_context();
|
||||||
cuda_assert(cuMemcpyHtoD(cuda_device_ptr(mem.device_pointer), (void*)mem.data_pointer, mem.memory_size()))
|
if(mem.device_pointer)
|
||||||
|
cuda_assert(cuMemcpyHtoD(cuda_device_ptr(mem.device_pointer), (void*)mem.data_pointer, mem.memory_size()))
|
||||||
cuda_pop_context();
|
cuda_pop_context();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,8 +337,13 @@ public:
|
|||||||
size_t size = elem*w*h;
|
size_t size = elem*w*h;
|
||||||
|
|
||||||
cuda_push_context();
|
cuda_push_context();
|
||||||
cuda_assert(cuMemcpyDtoH((uchar*)mem.data_pointer + offset,
|
if(mem.device_pointer) {
|
||||||
(CUdeviceptr)((uchar*)mem.device_pointer + offset), size))
|
cuda_assert(cuMemcpyDtoH((uchar*)mem.data_pointer + offset,
|
||||||
|
(CUdeviceptr)((uchar*)mem.device_pointer + offset), size))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memset((char*)mem.data_pointer + offset, 0, size);
|
||||||
|
}
|
||||||
cuda_pop_context();
|
cuda_pop_context();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,7 +352,8 @@ public:
|
|||||||
memset((void*)mem.data_pointer, 0, mem.memory_size());
|
memset((void*)mem.data_pointer, 0, mem.memory_size());
|
||||||
|
|
||||||
cuda_push_context();
|
cuda_push_context();
|
||||||
cuda_assert(cuMemsetD8(cuda_device_ptr(mem.device_pointer), 0, mem.memory_size()))
|
if(mem.device_pointer)
|
||||||
|
cuda_assert(cuMemsetD8(cuda_device_ptr(mem.device_pointer), 0, mem.memory_size()))
|
||||||
cuda_pop_context();
|
cuda_pop_context();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,13 +397,18 @@ public:
|
|||||||
default: assert(0); return;
|
default: assert(0); return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CUtexref texref;
|
CUtexref texref = NULL;
|
||||||
|
|
||||||
cuda_push_context();
|
cuda_push_context();
|
||||||
cuda_assert(cuModuleGetTexRef(&texref, cuModule, name))
|
cuda_assert(cuModuleGetTexRef(&texref, cuModule, name))
|
||||||
|
|
||||||
|
if(!texref) {
|
||||||
|
cuda_pop_context();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(interpolation) {
|
if(interpolation) {
|
||||||
CUarray handle;
|
CUarray handle = NULL;
|
||||||
CUDA_ARRAY_DESCRIPTOR desc;
|
CUDA_ARRAY_DESCRIPTOR desc;
|
||||||
|
|
||||||
desc.Width = mem.data_width;
|
desc.Width = mem.data_width;
|
||||||
@@ -406,6 +418,11 @@ public:
|
|||||||
|
|
||||||
cuda_assert(cuArrayCreate(&handle, &desc))
|
cuda_assert(cuArrayCreate(&handle, &desc))
|
||||||
|
|
||||||
|
if(!handle) {
|
||||||
|
cuda_pop_context();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(mem.data_height > 1) {
|
if(mem.data_height > 1) {
|
||||||
CUDA_MEMCPY2D param;
|
CUDA_MEMCPY2D param;
|
||||||
memset(¶m, 0, sizeof(param));
|
memset(¶m, 0, sizeof(param));
|
||||||
@@ -481,6 +498,9 @@ public:
|
|||||||
|
|
||||||
void path_trace(RenderTile& rtile, int sample)
|
void path_trace(RenderTile& rtile, int sample)
|
||||||
{
|
{
|
||||||
|
if(have_error())
|
||||||
|
return;
|
||||||
|
|
||||||
cuda_push_context();
|
cuda_push_context();
|
||||||
|
|
||||||
CUfunction cuPathTrace;
|
CUfunction cuPathTrace;
|
||||||
@@ -546,6 +566,9 @@ public:
|
|||||||
|
|
||||||
void tonemap(DeviceTask& task, device_ptr buffer, device_ptr rgba)
|
void tonemap(DeviceTask& task, device_ptr buffer, device_ptr rgba)
|
||||||
{
|
{
|
||||||
|
if(have_error())
|
||||||
|
return;
|
||||||
|
|
||||||
cuda_push_context();
|
cuda_push_context();
|
||||||
|
|
||||||
CUfunction cuFilmConvert;
|
CUfunction cuFilmConvert;
|
||||||
@@ -615,6 +638,9 @@ public:
|
|||||||
|
|
||||||
void shader(DeviceTask& task)
|
void shader(DeviceTask& task)
|
||||||
{
|
{
|
||||||
|
if(have_error())
|
||||||
|
return;
|
||||||
|
|
||||||
cuda_push_context();
|
cuda_push_context();
|
||||||
|
|
||||||
CUfunction cuDisplace;
|
CUfunction cuDisplace;
|
||||||
|
@@ -20,12 +20,12 @@ set(SRC
|
|||||||
set(SRC_HEADERS
|
set(SRC_HEADERS
|
||||||
kernel.h
|
kernel.h
|
||||||
kernel_accumulate.h
|
kernel_accumulate.h
|
||||||
kernel_attribute.h
|
|
||||||
kernel_bvh.h
|
kernel_bvh.h
|
||||||
kernel_camera.h
|
kernel_camera.h
|
||||||
kernel_compat_cpu.h
|
kernel_compat_cpu.h
|
||||||
kernel_compat_cuda.h
|
kernel_compat_cuda.h
|
||||||
kernel_compat_opencl.h
|
kernel_compat_opencl.h
|
||||||
|
kernel_curve.h
|
||||||
kernel_differential.h
|
kernel_differential.h
|
||||||
kernel_displace.h
|
kernel_displace.h
|
||||||
kernel_emission.h
|
kernel_emission.h
|
||||||
@@ -37,6 +37,7 @@ set(SRC_HEADERS
|
|||||||
kernel_object.h
|
kernel_object.h
|
||||||
kernel_passes.h
|
kernel_passes.h
|
||||||
kernel_path.h
|
kernel_path.h
|
||||||
|
kernel_primitive.h
|
||||||
kernel_projection.h
|
kernel_projection.h
|
||||||
kernel_random.h
|
kernel_random.h
|
||||||
kernel_shader.h
|
kernel_shader.h
|
||||||
|
@@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011, Blender Foundation.
|
|
||||||
*
|
|
||||||
* 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 2
|
|
||||||
* 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, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __KERNEL_ATTRIBUTE_CL__
|
|
||||||
#define __KERNEL_ATTRIBUTE_CL__
|
|
||||||
|
|
||||||
CCL_NAMESPACE_BEGIN
|
|
||||||
|
|
||||||
/* note: declared in kernel.h, have to add it here because kernel.h is not available */
|
|
||||||
bool kernel_osl_use(KernelGlobals *kg);
|
|
||||||
|
|
||||||
__device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id)
|
|
||||||
{
|
|
||||||
#ifdef __OSL__
|
|
||||||
if (kg->osl) {
|
|
||||||
return OSLShader::find_attribute(kg, sd, id);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
/* for SVM, find attribute by unique id */
|
|
||||||
uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
|
|
||||||
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
|
|
||||||
|
|
||||||
while(attr_map.x != id)
|
|
||||||
attr_map = kernel_tex_fetch(__attributes_map, ++attr_offset);
|
|
||||||
|
|
||||||
/* return result */
|
|
||||||
return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
|
||||||
|
|
||||||
#endif /* __KERNEL_ATTRIBUTE_CL__ */
|
|
@@ -205,6 +205,145 @@ __device_inline void bvh_triangle_intersect(KernelGlobals *kg, Intersection *ise
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __HAIR__
|
||||||
|
__device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect,
|
||||||
|
float3 P, float3 idir, uint visibility, int object, int curveAddr, int segment)
|
||||||
|
{
|
||||||
|
/* curve Intersection check */
|
||||||
|
|
||||||
|
int flags = kernel_data.curve_kernel_data.curveflags;
|
||||||
|
|
||||||
|
int prim = kernel_tex_fetch(__prim_index, curveAddr);
|
||||||
|
float4 v00 = kernel_tex_fetch(__curves, prim);
|
||||||
|
|
||||||
|
int k0 = __float_as_int(v00.x) + segment;
|
||||||
|
int k1 = k0 + 1;
|
||||||
|
|
||||||
|
float4 P1 = kernel_tex_fetch(__curve_keys, k0);
|
||||||
|
float4 P2 = kernel_tex_fetch(__curve_keys, k1);
|
||||||
|
|
||||||
|
float l = len(P2 - P1);
|
||||||
|
float r1 = P1.w;
|
||||||
|
float r2 = P2.w;
|
||||||
|
float mr = max(r1,r2);
|
||||||
|
float3 p1 = float4_to_float3(P1);
|
||||||
|
float3 p2 = float4_to_float3(P2);
|
||||||
|
float3 dif = P - p1;
|
||||||
|
float3 dir = 1.0f/idir;
|
||||||
|
|
||||||
|
float sp_r = mr + 0.5f * l;
|
||||||
|
float3 sphere_dif = P - ((p1 + p2) * 0.5f);
|
||||||
|
float sphere_b = dot(dir,sphere_dif);
|
||||||
|
sphere_dif = sphere_dif - sphere_b * dir;
|
||||||
|
sphere_b = dot(dir,sphere_dif);
|
||||||
|
float sdisc = sphere_b * sphere_b - len_squared(sphere_dif) + sp_r * sp_r;
|
||||||
|
if(sdisc < 0.0f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* obtain parameters and test midpoint distance for suitable modes*/
|
||||||
|
float3 tg = (p2 - p1) / l;
|
||||||
|
float gd = (r2 - r1) / l;
|
||||||
|
float dirz = dot(dir,tg);
|
||||||
|
float difz = dot(dif,tg);
|
||||||
|
|
||||||
|
float a = 1.0f - (dirz*dirz*(1 + gd*gd));
|
||||||
|
float halfb = (dot(dir,dif) - dirz*(difz + gd*(difz*gd + r1)));
|
||||||
|
|
||||||
|
float tcentre = -halfb/a;
|
||||||
|
float zcentre = difz + (dirz * tcentre);
|
||||||
|
|
||||||
|
if((tcentre > isect->t) && !(flags & CURVE_KN_ACCURATE))
|
||||||
|
return;
|
||||||
|
if((zcentre < 0 || zcentre > l) && !(flags & CURVE_KN_ACCURATE) && !(flags & CURVE_KN_INTERSECTCORRECTION))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* test minimum separation*/
|
||||||
|
float3 cprod = cross(tg, dir);
|
||||||
|
float3 cprod2 = cross(tg, dif);
|
||||||
|
float cprodsq = len_squared(cprod);
|
||||||
|
float cprod2sq = len_squared(cprod2);
|
||||||
|
float distscaled = dot(cprod,dif);
|
||||||
|
|
||||||
|
if(cprodsq == 0)
|
||||||
|
distscaled = cprod2sq;
|
||||||
|
else
|
||||||
|
distscaled = (distscaled*distscaled)/cprodsq;
|
||||||
|
|
||||||
|
if(distscaled > mr*mr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* calculate true intersection*/
|
||||||
|
float3 tdif = P - p1 + tcentre * dir;
|
||||||
|
float tdifz = dot(tdif,tg);
|
||||||
|
float tb = 2*(dot(dir,tdif) - dirz*(tdifz + gd*(tdifz*gd + r1)));
|
||||||
|
float tc = dot(tdif,tdif) - tdifz * tdifz * (1 + gd*gd) - r1*r1 - 2*r1*tdifz*gd;
|
||||||
|
float td = tb*tb - 4*a*tc;
|
||||||
|
|
||||||
|
if (td < 0.0f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
float rootd = 0.0f;
|
||||||
|
float correction = 0.0f;
|
||||||
|
if(flags & CURVE_KN_ACCURATE) {
|
||||||
|
rootd = sqrtf(td);
|
||||||
|
correction = ((-tb - rootd)/(2*a));
|
||||||
|
}
|
||||||
|
|
||||||
|
float t = tcentre + correction;
|
||||||
|
|
||||||
|
if(t < isect->t) {
|
||||||
|
|
||||||
|
if(flags & CURVE_KN_INTERSECTCORRECTION) {
|
||||||
|
rootd = sqrtf(td);
|
||||||
|
correction = ((-tb - rootd)/(2*a));
|
||||||
|
t = tcentre + correction;
|
||||||
|
}
|
||||||
|
|
||||||
|
float z = zcentre + (dirz * correction);
|
||||||
|
bool backface = false;
|
||||||
|
|
||||||
|
if(flags & CURVE_KN_BACKFACING && (t < 0.0f || z < 0 || z > l)) {
|
||||||
|
backface = true;
|
||||||
|
correction = ((-tb + rootd)/(2*a));
|
||||||
|
t = tcentre + correction;
|
||||||
|
z = zcentre + (dirz * correction);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(t > 0.0f && t < isect->t && z >= 0 && z <= l) {
|
||||||
|
|
||||||
|
if (flags & CURVE_KN_ENCLOSEFILTER) {
|
||||||
|
|
||||||
|
float enc_ratio = kernel_data.curve_kernel_data.encasing_ratio;
|
||||||
|
if((dot(P - p1, tg) > -r1 * enc_ratio) && (dot(P - p2, tg) < r2 * enc_ratio)) {
|
||||||
|
float a2 = 1.0f - (dirz*dirz*(1 + gd*gd*enc_ratio*enc_ratio));
|
||||||
|
float c2 = dot(dif,dif) - difz * difz * (1 + gd*gd*enc_ratio*enc_ratio) - r1*r1*enc_ratio*enc_ratio - 2*r1*difz*gd*enc_ratio;
|
||||||
|
if(a2*c2 < 0.0f)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __VISIBILITY_FLAG__
|
||||||
|
/* visibility flag test. we do it here under the assumption
|
||||||
|
* that most triangles are culled by node flags */
|
||||||
|
if(kernel_tex_fetch(__prim_visibility, curveAddr) & visibility)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* record intersection */
|
||||||
|
isect->prim = curveAddr;
|
||||||
|
isect->segment = segment;
|
||||||
|
isect->object = object;
|
||||||
|
isect->u = z/l;
|
||||||
|
isect->v = td/(4*a*a);
|
||||||
|
isect->t = t;
|
||||||
|
|
||||||
|
if(backface)
|
||||||
|
isect->u = -isect->u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
__device_inline bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect)
|
__device_inline bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect)
|
||||||
{
|
{
|
||||||
/* traversal stack in CUDA thread-local memory */
|
/* traversal stack in CUDA thread-local memory */
|
||||||
@@ -281,10 +420,16 @@ __device_inline bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint
|
|||||||
nodeAddr = traversalStack[stackPtr];
|
nodeAddr = traversalStack[stackPtr];
|
||||||
--stackPtr;
|
--stackPtr;
|
||||||
|
|
||||||
/* triangle intersection */
|
/* primitive intersection */
|
||||||
while(primAddr < primAddr2) {
|
while(primAddr < primAddr2) {
|
||||||
/* intersect ray against triangle */
|
/* intersect ray against primitive */
|
||||||
bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr);
|
#ifdef __HAIR__
|
||||||
|
uint segment = kernel_tex_fetch(__prim_segment, primAddr);
|
||||||
|
if(segment != ~0)
|
||||||
|
bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr);
|
||||||
|
|
||||||
/* shadow ray early termination */
|
/* shadow ray early termination */
|
||||||
if(visibility == PATH_RAY_SHADOW_OPAQUE && isect->prim != ~0)
|
if(visibility == PATH_RAY_SHADOW_OPAQUE && isect->prim != ~0)
|
||||||
@@ -401,10 +546,16 @@ __device_inline bool bvh_intersect_motion(KernelGlobals *kg, const Ray *ray, con
|
|||||||
nodeAddr = traversalStack[stackPtr];
|
nodeAddr = traversalStack[stackPtr];
|
||||||
--stackPtr;
|
--stackPtr;
|
||||||
|
|
||||||
/* triangle intersection */
|
/* primitive intersection */
|
||||||
while(primAddr < primAddr2) {
|
while(primAddr < primAddr2) {
|
||||||
/* intersect ray against triangle */
|
/* intersect ray against primitive */
|
||||||
bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr);
|
#ifdef __HAIR__
|
||||||
|
uint segment = kernel_tex_fetch(__prim_segment, primAddr);
|
||||||
|
if(segment != ~0)
|
||||||
|
bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr);
|
||||||
|
|
||||||
/* shadow ray early termination */
|
/* shadow ray early termination */
|
||||||
if(visibility == PATH_RAY_SHADOW_OPAQUE && isect->prim != ~0)
|
if(visibility == PATH_RAY_SHADOW_OPAQUE && isect->prim != ~0)
|
||||||
@@ -457,12 +608,15 @@ __device_inline float3 ray_offset(float3 P, float3 Ng)
|
|||||||
{
|
{
|
||||||
#ifdef __INTERSECTION_REFINE__
|
#ifdef __INTERSECTION_REFINE__
|
||||||
const float epsilon_f = 1e-5f;
|
const float epsilon_f = 1e-5f;
|
||||||
|
/* ideally this should match epsilon_f, but instancing/mblur
|
||||||
|
* precision makes it problematic */
|
||||||
|
const float epsilon_test = 1e-1f;
|
||||||
const int epsilon_i = 32;
|
const int epsilon_i = 32;
|
||||||
|
|
||||||
float3 res;
|
float3 res;
|
||||||
|
|
||||||
/* x component */
|
/* x component */
|
||||||
if(fabsf(P.x) < epsilon_f) {
|
if(fabsf(P.x) < epsilon_test) {
|
||||||
res.x = P.x + Ng.x*epsilon_f;
|
res.x = P.x + Ng.x*epsilon_f;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -472,7 +626,7 @@ __device_inline float3 ray_offset(float3 P, float3 Ng)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* y component */
|
/* y component */
|
||||||
if(fabsf(P.y) < epsilon_f) {
|
if(fabsf(P.y) < epsilon_test) {
|
||||||
res.y = P.y + Ng.y*epsilon_f;
|
res.y = P.y + Ng.y*epsilon_f;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -482,7 +636,7 @@ __device_inline float3 ray_offset(float3 P, float3 Ng)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* z component */
|
/* z component */
|
||||||
if(fabsf(P.z) < epsilon_f) {
|
if(fabsf(P.z) < epsilon_test) {
|
||||||
res.z = P.z + Ng.z*epsilon_f;
|
res.z = P.z + Ng.z*epsilon_f;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -542,5 +696,105 @@ __device_inline float3 bvh_triangle_refine(KernelGlobals *kg, ShaderData *sd, co
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __HAIR__
|
||||||
|
__device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray, float t)
|
||||||
|
{
|
||||||
|
int flag = kernel_data.curve_kernel_data.curveflags;
|
||||||
|
float3 P = ray->P;
|
||||||
|
float3 D = ray->D;
|
||||||
|
|
||||||
|
if(isect->object != ~0) {
|
||||||
|
#ifdef __OBJECT_MOTION__
|
||||||
|
Transform tfm = sd->ob_itfm;
|
||||||
|
#else
|
||||||
|
Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
P = transform_point(&tfm, P);
|
||||||
|
D = transform_direction(&tfm, D*t);
|
||||||
|
D = normalize_len(D, &t);
|
||||||
|
}
|
||||||
|
|
||||||
|
int prim = kernel_tex_fetch(__prim_index, isect->prim);
|
||||||
|
float4 v00 = kernel_tex_fetch(__curves, prim);
|
||||||
|
|
||||||
|
int k0 = __float_as_int(v00.x) + isect->segment;
|
||||||
|
int k1 = k0 + 1;
|
||||||
|
|
||||||
|
float4 P1 = kernel_tex_fetch(__curve_keys, k0);
|
||||||
|
float4 P2 = kernel_tex_fetch(__curve_keys, k1);
|
||||||
|
float l = len(P2 - P1);
|
||||||
|
float r1 = P1.w;
|
||||||
|
float r2 = P2.w;
|
||||||
|
float3 tg = float4_to_float3(P2 - P1) / l;
|
||||||
|
float3 dif = P - float4_to_float3(P1) + t * D;
|
||||||
|
float gd = ((r2 - r1)/l);
|
||||||
|
|
||||||
|
P = P + D*t;
|
||||||
|
|
||||||
|
dif = P - float4_to_float3(P1);
|
||||||
|
|
||||||
|
#ifdef __UV__
|
||||||
|
sd->u = dot(dif,tg)/l;
|
||||||
|
sd->v = 0.0f;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (flag & CURVE_KN_TRUETANGENTGNORMAL) {
|
||||||
|
sd->Ng = -(D - tg * (dot(tg,D) * kernel_data.curve_kernel_data.normalmix));
|
||||||
|
sd->Ng = normalize(sd->Ng);
|
||||||
|
if (flag & CURVE_KN_NORMALCORRECTION)
|
||||||
|
{
|
||||||
|
//sd->Ng = normalize(sd->Ng);
|
||||||
|
sd->Ng = sd->Ng - gd * tg;
|
||||||
|
sd->Ng = normalize(sd->Ng);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sd->Ng = (dif - tg * sd->u * l) / (P1.w + sd->u * l * gd);
|
||||||
|
if (gd != 0.0f) {
|
||||||
|
sd->Ng = sd->Ng - gd * tg ;
|
||||||
|
sd->Ng = normalize(sd->Ng);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sd->N = sd->Ng;
|
||||||
|
|
||||||
|
if (flag & CURVE_KN_TANGENTGNORMAL && !(flag & CURVE_KN_TRUETANGENTGNORMAL)) {
|
||||||
|
sd->N = -(D - tg * (dot(tg,D) * kernel_data.curve_kernel_data.normalmix));
|
||||||
|
sd->N = normalize(sd->N);
|
||||||
|
if (flag & CURVE_KN_NORMALCORRECTION) {
|
||||||
|
//sd->N = normalize(sd->N);
|
||||||
|
sd->N = sd->N - gd * tg;
|
||||||
|
sd->N = normalize(sd->N);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!(flag & CURVE_KN_TANGENTGNORMAL) && flag & CURVE_KN_TRUETANGENTGNORMAL) {
|
||||||
|
sd->N = (dif - tg * sd->u * l) / (P1.w + sd->u * l * gd);
|
||||||
|
if (gd != 0.0f) {
|
||||||
|
sd->N = sd->N - gd * tg ;
|
||||||
|
sd->N = normalize(sd->N);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DPDU__
|
||||||
|
/* dPdu/dPdv */
|
||||||
|
sd->dPdu = tg;
|
||||||
|
sd->dPdv = cross(tg,sd->Ng);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(isect->object != ~0) {
|
||||||
|
#ifdef __OBJECT_MOTION__
|
||||||
|
Transform tfm = sd->ob_tfm;
|
||||||
|
#else
|
||||||
|
Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
P = transform_point(&tfm, P);
|
||||||
|
}
|
||||||
|
|
||||||
|
return P;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
|
||||||
|
141
intern/cycles/kernel/kernel_curve.h
Normal file
141
intern/cycles/kernel/kernel_curve.h
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Blender Foundation.
|
||||||
|
*
|
||||||
|
* 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 2
|
||||||
|
* 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, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
CCL_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
#ifdef __HAIR__
|
||||||
|
|
||||||
|
/* curve attributes */
|
||||||
|
|
||||||
|
__device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
|
||||||
|
{
|
||||||
|
if(elem == ATTR_ELEMENT_CURVE) {
|
||||||
|
#ifdef __RAY_DIFFERENTIALS__
|
||||||
|
if(dx) *dx = 0.0f;
|
||||||
|
if(dy) *dy = 0.0f;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return kernel_tex_fetch(__attributes_float, offset + sd->prim);
|
||||||
|
}
|
||||||
|
else if(elem == ATTR_ELEMENT_CURVE_KEY) {
|
||||||
|
float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
|
||||||
|
int k0 = __float_as_int(curvedata.x) + sd->segment;
|
||||||
|
int k1 = k0 + 1;
|
||||||
|
|
||||||
|
float f0 = kernel_tex_fetch(__attributes_float, offset + k0);
|
||||||
|
float f1 = kernel_tex_fetch(__attributes_float, offset + k1);
|
||||||
|
|
||||||
|
#ifdef __RAY_DIFFERENTIALS__
|
||||||
|
if(dx) *dx = sd->du.dx*(f1 - f0);
|
||||||
|
if(dy) *dy = 0.0f;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (1.0f - sd->u)*f0 + sd->u*f1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#ifdef __RAY_DIFFERENTIALS__
|
||||||
|
if(dx) *dx = 0.0f;
|
||||||
|
if(dy) *dy = 0.0f;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
|
||||||
|
{
|
||||||
|
if(elem == ATTR_ELEMENT_CURVE) {
|
||||||
|
/* idea: we can't derive any useful differentials here, but for tiled
|
||||||
|
* mipmap image caching it would be useful to avoid reading the highest
|
||||||
|
* detail level always. maybe a derivative based on the hair density
|
||||||
|
* could be computed somehow? */
|
||||||
|
#ifdef __RAY_DIFFERENTIALS__
|
||||||
|
if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->prim));
|
||||||
|
}
|
||||||
|
else if(elem == ATTR_ELEMENT_CURVE_KEY) {
|
||||||
|
float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
|
||||||
|
int k0 = __float_as_int(curvedata.x) + sd->segment;
|
||||||
|
int k1 = k0 + 1;
|
||||||
|
|
||||||
|
float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + k0));
|
||||||
|
float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + k1));
|
||||||
|
|
||||||
|
#ifdef __RAY_DIFFERENTIALS__
|
||||||
|
if(dx) *dx = sd->du.dx*(f1 - f0);
|
||||||
|
if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (1.0f - sd->u)*f0 + sd->u*f1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#ifdef __RAY_DIFFERENTIALS__
|
||||||
|
if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hair info node functions */
|
||||||
|
|
||||||
|
__device float curve_thickness(KernelGlobals *kg, ShaderData *sd)
|
||||||
|
{
|
||||||
|
float r = 0.0f;
|
||||||
|
|
||||||
|
if(sd->segment != ~0) {
|
||||||
|
float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
|
||||||
|
int k0 = __float_as_int(curvedata.x) + sd->segment;
|
||||||
|
int k1 = k0 + 1;
|
||||||
|
|
||||||
|
float4 P1 = kernel_tex_fetch(__curve_keys, k0);
|
||||||
|
float4 P2 = kernel_tex_fetch(__curve_keys, k1);
|
||||||
|
r = (P2.w - P1.w) * sd->u + P1.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r*2.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
__device float3 curve_tangent_normal(KernelGlobals *kg, ShaderData *sd)
|
||||||
|
{
|
||||||
|
float3 tgN = make_float3(0.0f,0.0f,0.0f);
|
||||||
|
|
||||||
|
if(sd->segment != ~0) {
|
||||||
|
float normalmix = kernel_data.curve_kernel_data.normalmix;
|
||||||
|
|
||||||
|
tgN = -(-sd->I - sd->dPdu * (dot(sd->dPdu,-sd->I) * normalmix / len_squared(sd->dPdu)));
|
||||||
|
tgN = normalize(tgN);
|
||||||
|
|
||||||
|
/* need to find suitable scaled gd for corrected normal */
|
||||||
|
#if 0
|
||||||
|
if (kernel_data.curve_kernel_data.use_tangent_normal_correction)
|
||||||
|
tgN = normalize(tgN - gd * sd->dPdu);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return tgN;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CCL_NAMESPACE_END
|
||||||
|
|
@@ -47,7 +47,13 @@ __device float3 direct_emissive_eval(KernelGlobals *kg, float rando,
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, u, v, t, time);
|
#ifdef __HAIR__
|
||||||
|
if(ls->type == LIGHT_STRAND)
|
||||||
|
shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, u, v, t, time, ls->prim);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, u, v, t, time);
|
||||||
|
|
||||||
ls->Ng = sd.Ng;
|
ls->Ng = sd.Ng;
|
||||||
|
|
||||||
/* no path flag, we're evaluating this for all closures. that's weak but
|
/* no path flag, we're evaluating this for all closures. that's weak but
|
||||||
@@ -150,7 +156,11 @@ __device float3 indirect_emission(KernelGlobals *kg, ShaderData *sd, float t, in
|
|||||||
/* evaluate emissive closure */
|
/* evaluate emissive closure */
|
||||||
float3 L = shader_emissive_eval(kg, sd);
|
float3 L = shader_emissive_eval(kg, sd);
|
||||||
|
|
||||||
|
#ifdef __HAIR__
|
||||||
|
if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_SAMPLE_AS_LIGHT) && (sd->segment == ~0)) {
|
||||||
|
#else
|
||||||
if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_SAMPLE_AS_LIGHT)) {
|
if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_SAMPLE_AS_LIGHT)) {
|
||||||
|
#endif
|
||||||
/* multiple importance sampling, get triangle light pdf,
|
/* multiple importance sampling, get triangle light pdf,
|
||||||
* and compute weight with respect to BSDF pdf */
|
* and compute weight with respect to BSDF pdf */
|
||||||
float pdf = triangle_light_pdf(kg, sd->Ng, sd->I, t);
|
float pdf = triangle_light_pdf(kg, sd->Ng, sd->I, t);
|
||||||
|
@@ -326,6 +326,61 @@ __device float triangle_light_pdf(KernelGlobals *kg,
|
|||||||
return (t*t*kernel_data.integrator.pdf_triangles)/cos_pi;
|
return (t*t*kernel_data.integrator.pdf_triangles)/cos_pi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __HAIR__
|
||||||
|
/* Strand Light */
|
||||||
|
|
||||||
|
__device void curve_segment_light_sample(KernelGlobals *kg, int prim, int object,
|
||||||
|
int segment, float randu, float randv, float time, LightSample *ls)
|
||||||
|
{
|
||||||
|
/* this strand code needs completion */
|
||||||
|
float4 v00 = kernel_tex_fetch(__curves, prim);
|
||||||
|
|
||||||
|
int k0 = __float_as_int(v00.x) + segment;
|
||||||
|
int k1 = k0 + 1;
|
||||||
|
|
||||||
|
float4 P1 = kernel_tex_fetch(__curve_keys, k0);
|
||||||
|
float4 P2 = kernel_tex_fetch(__curve_keys, k1);
|
||||||
|
|
||||||
|
float l = len(P2 - P1);
|
||||||
|
|
||||||
|
float r1 = P1.w;
|
||||||
|
float r2 = P2.w;
|
||||||
|
float3 tg = float4_to_float3(P2 - P1) / l;
|
||||||
|
float3 xc = make_float3(tg.x * tg.z, tg.y * tg.z, -(tg.x * tg.x + tg.y * tg.y));
|
||||||
|
if (dot(xc, xc) == 0.0f)
|
||||||
|
xc = make_float3(tg.x * tg.y, -(tg.x * tg.x + tg.z * tg.z), tg.z * tg.y);
|
||||||
|
xc = normalize(xc);
|
||||||
|
float3 yc = cross(tg, xc);
|
||||||
|
float gd = ((r2 - r1)/l);
|
||||||
|
|
||||||
|
/* normal currently ignores gradient */
|
||||||
|
ls->Ng = sinf(2 * M_PI_F * randv) * xc + cosf(2 * M_PI_F * randv) * yc;
|
||||||
|
ls->P = randu * l * tg + (gd * l + r1) * ls->Ng;
|
||||||
|
ls->object = object;
|
||||||
|
ls->prim = prim;
|
||||||
|
ls->t = 0.0f;
|
||||||
|
ls->type = LIGHT_STRAND;
|
||||||
|
ls->eval_fac = 1.0f;
|
||||||
|
ls->shader = __float_as_int(v00.z);
|
||||||
|
|
||||||
|
#ifdef __INSTANCING__
|
||||||
|
/* instance transform */
|
||||||
|
if(ls->object >= 0) {
|
||||||
|
#ifdef __OBJECT_MOTION__
|
||||||
|
Transform itfm;
|
||||||
|
Transform tfm = object_fetch_transform_motion_test(kg, object, time, &itfm);
|
||||||
|
#else
|
||||||
|
Transform tfm = object_fetch_transform(kg, ls->object, OBJECT_TRANSFORM);
|
||||||
|
Transform itfm = object_fetch_transform(kg, ls->object, OBJECT_INVERSE_TRANSFORM);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ls->P = transform_point(&tfm, ls->P);
|
||||||
|
ls->Ng = normalize(transform_direction(&tfm, ls->Ng));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Light Distribution */
|
/* Light Distribution */
|
||||||
|
|
||||||
__device int light_distribution_sample(KernelGlobals *kg, float randt)
|
__device int light_distribution_sample(KernelGlobals *kg, float randt)
|
||||||
@@ -365,10 +420,19 @@ __device void light_sample(KernelGlobals *kg, float randt, float randu, float ra
|
|||||||
/* fetch light data */
|
/* fetch light data */
|
||||||
float4 l = kernel_tex_fetch(__light_distribution, index);
|
float4 l = kernel_tex_fetch(__light_distribution, index);
|
||||||
int prim = __float_as_int(l.y);
|
int prim = __float_as_int(l.y);
|
||||||
|
#ifdef __HAIR__
|
||||||
|
int segment = __float_as_int(l.z);
|
||||||
|
#endif
|
||||||
|
|
||||||
if(prim >= 0) {
|
if(prim >= 0) {
|
||||||
int object = __float_as_int(l.w);
|
int object = __float_as_int(l.w);
|
||||||
triangle_light_sample(kg, prim, object, randu, randv, time, ls);
|
|
||||||
|
#ifdef __HAIR__
|
||||||
|
if (segment != ~0)
|
||||||
|
curve_segment_light_sample(kg, prim, object, segment, randu, randv, time, ls);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
triangle_light_sample(kg, prim, object, randu, randv, time, ls);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int point = -prim-1;
|
int point = -prim-1;
|
||||||
|
@@ -70,11 +70,11 @@ __device_inline void kernel_write_data_passes(KernelGlobals *kg, __global float
|
|||||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_normal, sample, normal);
|
kernel_write_pass_float3(buffer + kernel_data.film.pass_normal, sample, normal);
|
||||||
}
|
}
|
||||||
if(flag & PASS_UV) {
|
if(flag & PASS_UV) {
|
||||||
float3 uv = triangle_uv(kg, sd);
|
float3 uv = primitive_uv(kg, sd);
|
||||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_uv, sample, uv);
|
kernel_write_pass_float3(buffer + kernel_data.film.pass_uv, sample, uv);
|
||||||
}
|
}
|
||||||
if(flag & PASS_MOTION) {
|
if(flag & PASS_MOTION) {
|
||||||
float4 speed = triangle_motion_vector(kg, sd);
|
float4 speed = primitive_motion_vector(kg, sd);
|
||||||
kernel_write_pass_float4(buffer + kernel_data.film.pass_motion, sample, speed);
|
kernel_write_pass_float4(buffer + kernel_data.film.pass_motion, sample, speed);
|
||||||
kernel_write_pass_float(buffer + kernel_data.film.pass_motion_weight, sample, 1.0f);
|
kernel_write_pass_float(buffer + kernel_data.film.pass_motion_weight, sample, 1.0f);
|
||||||
}
|
}
|
||||||
|
@@ -24,9 +24,10 @@
|
|||||||
#include "kernel_montecarlo.h"
|
#include "kernel_montecarlo.h"
|
||||||
#include "kernel_projection.h"
|
#include "kernel_projection.h"
|
||||||
#include "kernel_object.h"
|
#include "kernel_object.h"
|
||||||
#include "kernel_attribute.h"
|
|
||||||
#include "kernel_projection.h"
|
|
||||||
#include "kernel_triangle.h"
|
#include "kernel_triangle.h"
|
||||||
|
#include "kernel_curve.h"
|
||||||
|
#include "kernel_primitive.h"
|
||||||
|
#include "kernel_projection.h"
|
||||||
#ifdef __QBVH__
|
#ifdef __QBVH__
|
||||||
#include "kernel_qbvh.h"
|
#include "kernel_qbvh.h"
|
||||||
#else
|
#else
|
||||||
|
185
intern/cycles/kernel/kernel_primitive.h
Normal file
185
intern/cycles/kernel/kernel_primitive.h
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Blender Foundation.
|
||||||
|
*
|
||||||
|
* 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 2
|
||||||
|
* 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, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __KERNEL_ATTRIBUTE_CL__
|
||||||
|
#define __KERNEL_ATTRIBUTE_CL__
|
||||||
|
|
||||||
|
CCL_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
/* attribute lookup */
|
||||||
|
|
||||||
|
__device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id, AttributeElement *elem)
|
||||||
|
{
|
||||||
|
if(sd->object == ~0)
|
||||||
|
return (int)ATTR_STD_NOT_FOUND;
|
||||||
|
|
||||||
|
#ifdef __OSL__
|
||||||
|
if (kg->osl) {
|
||||||
|
return OSLShader::find_attribute(kg, sd, id, elem);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* for SVM, find attribute by unique id */
|
||||||
|
uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
|
||||||
|
#ifdef __HAIR__
|
||||||
|
attr_offset = (sd->segment == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE;
|
||||||
|
#endif
|
||||||
|
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
|
||||||
|
|
||||||
|
while(attr_map.x != id) {
|
||||||
|
attr_offset += ATTR_PRIM_TYPES;
|
||||||
|
attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
*elem = (AttributeElement)attr_map.y;
|
||||||
|
|
||||||
|
/* return result */
|
||||||
|
return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
|
||||||
|
{
|
||||||
|
#ifdef __HAIR__
|
||||||
|
if(sd->segment == ~0)
|
||||||
|
#endif
|
||||||
|
return triangle_attribute_float(kg, sd, elem, offset, dx, dy);
|
||||||
|
#ifdef __HAIR__
|
||||||
|
else
|
||||||
|
return curve_attribute_float(kg, sd, elem, offset, dx, dy);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
__device float3 primitive_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
|
||||||
|
{
|
||||||
|
#ifdef __HAIR__
|
||||||
|
if(sd->segment == ~0)
|
||||||
|
#endif
|
||||||
|
return triangle_attribute_float3(kg, sd, elem, offset, dx, dy);
|
||||||
|
#ifdef __HAIR__
|
||||||
|
else
|
||||||
|
return curve_attribute_float3(kg, sd, elem, offset, dx, dy);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
__device float3 primitive_uv(KernelGlobals *kg, ShaderData *sd)
|
||||||
|
{
|
||||||
|
AttributeElement elem_uv;
|
||||||
|
int offset_uv = find_attribute(kg, sd, ATTR_STD_UV, &elem_uv);
|
||||||
|
|
||||||
|
if(offset_uv == ATTR_STD_NOT_FOUND)
|
||||||
|
return make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
float3 uv = primitive_attribute_float3(kg, sd, elem_uv, offset_uv, NULL, NULL);
|
||||||
|
uv.z = 1.0f;
|
||||||
|
return uv;
|
||||||
|
}
|
||||||
|
|
||||||
|
__device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd)
|
||||||
|
{
|
||||||
|
#ifdef __HAIR__
|
||||||
|
if(sd->segment != ~0)
|
||||||
|
return normalize(sd->dPdu);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* try to create spherical tangent from generated coordinates */
|
||||||
|
AttributeElement attr_elem;
|
||||||
|
int attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED, &attr_elem);
|
||||||
|
|
||||||
|
if(attr_offset != ATTR_STD_NOT_FOUND) {
|
||||||
|
float3 data = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
|
||||||
|
data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f);
|
||||||
|
object_normal_transform(kg, sd, &data);
|
||||||
|
return cross(sd->N, normalize(cross(data, sd->N)));;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* otherwise use surface derivatives */
|
||||||
|
return normalize(sd->dPdu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* motion */
|
||||||
|
|
||||||
|
__device float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *sd)
|
||||||
|
{
|
||||||
|
float3 motion_pre = sd->P, motion_post = sd->P;
|
||||||
|
|
||||||
|
/* deformation motion */
|
||||||
|
AttributeElement elem_pre, elem_post;
|
||||||
|
int offset_pre = find_attribute(kg, sd, ATTR_STD_MOTION_PRE, &elem_pre);
|
||||||
|
int offset_post = find_attribute(kg, sd, ATTR_STD_MOTION_POST, &elem_post);
|
||||||
|
|
||||||
|
if(offset_pre != ATTR_STD_NOT_FOUND)
|
||||||
|
motion_pre = primitive_attribute_float3(kg, sd, elem_pre, offset_pre, NULL, NULL);
|
||||||
|
if(offset_post != ATTR_STD_NOT_FOUND)
|
||||||
|
motion_post = primitive_attribute_float3(kg, sd, elem_post, offset_post, NULL, NULL);
|
||||||
|
|
||||||
|
/* object motion. note that depending on the mesh having motion vectors, this
|
||||||
|
* transformation was set match the world/object space of motion_pre/post */
|
||||||
|
Transform tfm;
|
||||||
|
|
||||||
|
tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_PRE);
|
||||||
|
motion_pre = transform_point(&tfm, motion_pre);
|
||||||
|
|
||||||
|
tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_POST);
|
||||||
|
motion_post = transform_point(&tfm, motion_post);
|
||||||
|
|
||||||
|
float3 P;
|
||||||
|
|
||||||
|
/* camera motion, for perspective/orthographic motion.pre/post will be a
|
||||||
|
* world-to-raster matrix, for panorama it's world-to-camera */
|
||||||
|
if (kernel_data.cam.type != CAMERA_PANORAMA) {
|
||||||
|
tfm = kernel_data.cam.worldtoraster;
|
||||||
|
P = transform_perspective(&tfm, sd->P);
|
||||||
|
|
||||||
|
tfm = kernel_data.cam.motion.pre;
|
||||||
|
motion_pre = transform_perspective(&tfm, motion_pre);
|
||||||
|
|
||||||
|
tfm = kernel_data.cam.motion.post;
|
||||||
|
motion_post = transform_perspective(&tfm, motion_post);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tfm = kernel_data.cam.worldtocamera;
|
||||||
|
P = normalize(transform_point(&tfm, sd->P));
|
||||||
|
P = float2_to_float3(direction_to_panorama(kg, P));
|
||||||
|
P.x *= kernel_data.cam.width;
|
||||||
|
P.y *= kernel_data.cam.height;
|
||||||
|
|
||||||
|
tfm = kernel_data.cam.motion.pre;
|
||||||
|
motion_pre = normalize(transform_point(&tfm, motion_pre));
|
||||||
|
motion_pre = float2_to_float3(direction_to_panorama(kg, motion_pre));
|
||||||
|
motion_pre.x *= kernel_data.cam.width;
|
||||||
|
motion_pre.y *= kernel_data.cam.height;
|
||||||
|
|
||||||
|
tfm = kernel_data.cam.motion.post;
|
||||||
|
motion_post = normalize(transform_point(&tfm, motion_post));
|
||||||
|
motion_post = float2_to_float3(direction_to_panorama(kg, motion_post));
|
||||||
|
motion_post.x *= kernel_data.cam.width;
|
||||||
|
motion_post.y *= kernel_data.cam.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
motion_pre = motion_pre - P;
|
||||||
|
motion_post = P - motion_post;
|
||||||
|
|
||||||
|
return make_float4(motion_pre.x, motion_pre.y, motion_post.x, motion_post.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
CCL_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif /* __KERNEL_ATTRIBUTE_CL__ */
|
@@ -56,24 +56,11 @@ __device_noinline void shader_setup_object_transforms(KernelGlobals *kg, ShaderD
|
|||||||
__device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
|
__device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
|
||||||
const Intersection *isect, const Ray *ray)
|
const Intersection *isect, const Ray *ray)
|
||||||
{
|
{
|
||||||
/* fetch triangle data */
|
|
||||||
int prim = kernel_tex_fetch(__prim_index, isect->prim);
|
|
||||||
float4 Ns = kernel_tex_fetch(__tri_normal, prim);
|
|
||||||
float3 Ng = make_float3(Ns.x, Ns.y, Ns.z);
|
|
||||||
int shader = __float_as_int(Ns.w);
|
|
||||||
|
|
||||||
/* triangle */
|
|
||||||
#ifdef __INSTANCING__
|
#ifdef __INSTANCING__
|
||||||
sd->object = (isect->object == ~0)? kernel_tex_fetch(__prim_object, isect->prim): isect->object;
|
sd->object = (isect->object == ~0)? kernel_tex_fetch(__prim_object, isect->prim): isect->object;
|
||||||
#endif
|
#endif
|
||||||
sd->prim = prim;
|
|
||||||
#ifdef __UV__
|
|
||||||
sd->u = isect->u;
|
|
||||||
sd->v = isect->v;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
sd->flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*2);
|
sd->flag = kernel_tex_fetch(__object_flag, sd->object);
|
||||||
sd->flag |= kernel_tex_fetch(__object_flag, sd->object);
|
|
||||||
|
|
||||||
/* matrices and time */
|
/* matrices and time */
|
||||||
#ifdef __OBJECT_MOTION__
|
#ifdef __OBJECT_MOTION__
|
||||||
@@ -81,23 +68,63 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
|
|||||||
sd->time = ray->time;
|
sd->time = ray->time;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* vectors */
|
sd->prim = kernel_tex_fetch(__prim_index, isect->prim);
|
||||||
sd->P = bvh_triangle_refine(kg, sd, isect, ray);
|
|
||||||
sd->Ng = Ng;
|
|
||||||
sd->N = Ng;
|
|
||||||
sd->I = -ray->D;
|
|
||||||
sd->shader = shader;
|
|
||||||
sd->ray_length = isect->t;
|
sd->ray_length = isect->t;
|
||||||
|
|
||||||
/* smooth normal */
|
#ifdef __HAIR__
|
||||||
if(sd->shader & SHADER_SMOOTH_NORMAL)
|
if(kernel_tex_fetch(__prim_segment, isect->prim) != ~0) {
|
||||||
sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
|
/* Strand Shader setting*/
|
||||||
|
float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
|
||||||
|
|
||||||
|
sd->shader = __float_as_int(curvedata.z);
|
||||||
|
sd->segment = isect->segment;
|
||||||
|
|
||||||
|
float tcorr = isect->t;
|
||||||
|
if(kernel_data.curve_kernel_data.curveflags & CURVE_KN_POSTINTERSECTCORRECTION) {
|
||||||
|
tcorr = (isect->u < 0)? tcorr + sqrtf(isect->v) : tcorr - sqrtf(isect->v);
|
||||||
|
sd->ray_length = tcorr;
|
||||||
|
}
|
||||||
|
|
||||||
|
sd->P = bvh_curve_refine(kg, sd, isect, ray, tcorr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#endif
|
||||||
|
/* fetch triangle data */
|
||||||
|
float4 Ns = kernel_tex_fetch(__tri_normal, sd->prim);
|
||||||
|
float3 Ng = make_float3(Ns.x, Ns.y, Ns.z);
|
||||||
|
sd->shader = __float_as_int(Ns.w);
|
||||||
|
|
||||||
|
#ifdef __HAIR__
|
||||||
|
sd->segment = ~0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __UV__
|
||||||
|
sd->u = isect->u;
|
||||||
|
sd->v = isect->v;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* vectors */
|
||||||
|
sd->P = bvh_triangle_refine(kg, sd, isect, ray);
|
||||||
|
sd->Ng = Ng;
|
||||||
|
sd->N = Ng;
|
||||||
|
|
||||||
|
/* smooth normal */
|
||||||
|
if(sd->shader & SHADER_SMOOTH_NORMAL)
|
||||||
|
sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
|
||||||
|
|
||||||
#ifdef __DPDU__
|
#ifdef __DPDU__
|
||||||
/* dPdu/dPdv */
|
/* dPdu/dPdv */
|
||||||
triangle_dPdudv(kg, &sd->dPdu, &sd->dPdv, sd->prim);
|
triangle_dPdudv(kg, &sd->dPdu, &sd->dPdv, sd->prim);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __HAIR__
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sd->I = -ray->D;
|
||||||
|
|
||||||
|
sd->flag |= kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2);
|
||||||
|
|
||||||
#ifdef __INSTANCING__
|
#ifdef __INSTANCING__
|
||||||
if(isect->object != ~0) {
|
if(isect->object != ~0) {
|
||||||
/* instance transform */
|
/* instance transform */
|
||||||
@@ -135,7 +162,7 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
|
|||||||
|
|
||||||
__device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
|
__device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
|
||||||
const float3 P, const float3 Ng, const float3 I,
|
const float3 P, const float3 Ng, const float3 I,
|
||||||
int shader, int object, int prim, float u, float v, float t, float time)
|
int shader, int object, int prim, float u, float v, float t, float time, int segment = ~0)
|
||||||
{
|
{
|
||||||
/* vectors */
|
/* vectors */
|
||||||
sd->P = P;
|
sd->P = P;
|
||||||
@@ -143,11 +170,15 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
|
|||||||
sd->Ng = Ng;
|
sd->Ng = Ng;
|
||||||
sd->I = I;
|
sd->I = I;
|
||||||
sd->shader = shader;
|
sd->shader = shader;
|
||||||
|
#ifdef __HAIR__
|
||||||
|
sd->segment = segment;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* primitive */
|
/* primitive */
|
||||||
#ifdef __INSTANCING__
|
#ifdef __INSTANCING__
|
||||||
sd->object = object;
|
sd->object = object;
|
||||||
#endif
|
#endif
|
||||||
|
/* currently no access to bvh prim index for strand sd->prim - this will cause errors with needs fixing*/
|
||||||
sd->prim = prim;
|
sd->prim = prim;
|
||||||
#ifdef __UV__
|
#ifdef __UV__
|
||||||
sd->u = u;
|
sd->u = u;
|
||||||
@@ -183,8 +214,13 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* smooth normal */
|
/* smooth normal */
|
||||||
|
#ifdef __HAIR__
|
||||||
|
if(sd->shader & SHADER_SMOOTH_NORMAL && sd->segment == ~0) {
|
||||||
|
sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
|
||||||
|
#else
|
||||||
if(sd->shader & SHADER_SMOOTH_NORMAL) {
|
if(sd->shader & SHADER_SMOOTH_NORMAL) {
|
||||||
sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
|
sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __INSTANCING__
|
#ifdef __INSTANCING__
|
||||||
if(instanced)
|
if(instanced)
|
||||||
@@ -194,10 +230,17 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
|
|||||||
|
|
||||||
#ifdef __DPDU__
|
#ifdef __DPDU__
|
||||||
/* dPdu/dPdv */
|
/* dPdu/dPdv */
|
||||||
|
#ifdef __HAIR__
|
||||||
|
if(sd->prim == ~0 || sd->segment != ~0) {
|
||||||
|
sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
#else
|
||||||
if(sd->prim == ~0) {
|
if(sd->prim == ~0) {
|
||||||
sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
|
sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
|
sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
else {
|
else {
|
||||||
triangle_dPdudv(kg, &sd->dPdu, &sd->dPdv, sd->prim);
|
triangle_dPdudv(kg, &sd->dPdu, &sd->dPdv, sd->prim);
|
||||||
|
|
||||||
@@ -279,6 +322,9 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData
|
|||||||
sd->object = ~0;
|
sd->object = ~0;
|
||||||
#endif
|
#endif
|
||||||
sd->prim = ~0;
|
sd->prim = ~0;
|
||||||
|
#ifdef __HAIR__
|
||||||
|
sd->segment = ~0;
|
||||||
|
#endif
|
||||||
#ifdef __UV__
|
#ifdef __UV__
|
||||||
sd->u = 0.0f;
|
sd->u = 0.0f;
|
||||||
sd->v = 0.0f;
|
sd->v = 0.0f;
|
||||||
@@ -732,8 +778,20 @@ __device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd, Shader
|
|||||||
__device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect)
|
__device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect)
|
||||||
{
|
{
|
||||||
int prim = kernel_tex_fetch(__prim_index, isect->prim);
|
int prim = kernel_tex_fetch(__prim_index, isect->prim);
|
||||||
float4 Ns = kernel_tex_fetch(__tri_normal, prim);
|
int shader = 0;
|
||||||
int shader = __float_as_int(Ns.w);
|
|
||||||
|
#ifdef __HAIR__
|
||||||
|
if(kernel_tex_fetch(__prim_segment, isect->prim) == ~0) {
|
||||||
|
#endif
|
||||||
|
float4 Ns = kernel_tex_fetch(__tri_normal, prim);
|
||||||
|
shader = __float_as_int(Ns.w);
|
||||||
|
#ifdef __HAIR__
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
float4 str = kernel_tex_fetch(__curves, prim);
|
||||||
|
shader = __float_as_int(str.z);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
int flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*2);
|
int flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*2);
|
||||||
|
|
||||||
return (flag & SD_HAS_SURFACE_TRANSPARENT) != 0;
|
return (flag & SD_HAS_SURFACE_TRANSPARENT) != 0;
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
/* bvh */
|
/* bvh */
|
||||||
KERNEL_TEX(float4, texture_float4, __bvh_nodes)
|
KERNEL_TEX(float4, texture_float4, __bvh_nodes)
|
||||||
KERNEL_TEX(float4, texture_float4, __tri_woop)
|
KERNEL_TEX(float4, texture_float4, __tri_woop)
|
||||||
|
KERNEL_TEX(uint, texture_uint, __prim_segment)
|
||||||
KERNEL_TEX(uint, texture_uint, __prim_visibility)
|
KERNEL_TEX(uint, texture_uint, __prim_visibility)
|
||||||
KERNEL_TEX(uint, texture_uint, __prim_index)
|
KERNEL_TEX(uint, texture_uint, __prim_index)
|
||||||
KERNEL_TEX(uint, texture_uint, __prim_object)
|
KERNEL_TEX(uint, texture_uint, __prim_object)
|
||||||
@@ -42,6 +43,10 @@ KERNEL_TEX(float4, texture_float4, __tri_vnormal)
|
|||||||
KERNEL_TEX(float4, texture_float4, __tri_vindex)
|
KERNEL_TEX(float4, texture_float4, __tri_vindex)
|
||||||
KERNEL_TEX(float4, texture_float4, __tri_verts)
|
KERNEL_TEX(float4, texture_float4, __tri_verts)
|
||||||
|
|
||||||
|
/* curves */
|
||||||
|
KERNEL_TEX(float4, texture_float4, __curves)
|
||||||
|
KERNEL_TEX(float4, texture_float4, __curve_keys)
|
||||||
|
|
||||||
/* attributes */
|
/* attributes */
|
||||||
KERNEL_TEX(uint4, texture_uint4, __attributes_map)
|
KERNEL_TEX(uint4, texture_uint4, __attributes_map)
|
||||||
KERNEL_TEX(float, texture_float, __attributes_float)
|
KERNEL_TEX(float, texture_float, __attributes_float)
|
||||||
|
@@ -190,82 +190,5 @@ __device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData *s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* motion */
|
|
||||||
|
|
||||||
__device float4 triangle_motion_vector(KernelGlobals *kg, ShaderData *sd)
|
|
||||||
{
|
|
||||||
float3 motion_pre = sd->P, motion_post = sd->P;
|
|
||||||
|
|
||||||
/* deformation motion */
|
|
||||||
int offset_pre = find_attribute(kg, sd, ATTR_STD_MOTION_PRE);
|
|
||||||
int offset_post = find_attribute(kg, sd, ATTR_STD_MOTION_POST);
|
|
||||||
|
|
||||||
if(offset_pre != ATTR_STD_NOT_FOUND)
|
|
||||||
motion_pre = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_pre, NULL, NULL);
|
|
||||||
if(offset_post != ATTR_STD_NOT_FOUND)
|
|
||||||
motion_post = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_post, NULL, NULL);
|
|
||||||
|
|
||||||
/* object motion. note that depending on the mesh having motion vectors, this
|
|
||||||
* transformation was set match the world/object space of motion_pre/post */
|
|
||||||
Transform tfm;
|
|
||||||
|
|
||||||
tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_PRE);
|
|
||||||
motion_pre = transform_point(&tfm, motion_pre);
|
|
||||||
|
|
||||||
tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_POST);
|
|
||||||
motion_post = transform_point(&tfm, motion_post);
|
|
||||||
|
|
||||||
float3 P;
|
|
||||||
|
|
||||||
/* camera motion, for perspective/orthographic motion.pre/post will be a
|
|
||||||
* world-to-raster matrix, for panorama it's world-to-camera */
|
|
||||||
if (kernel_data.cam.type != CAMERA_PANORAMA) {
|
|
||||||
tfm = kernel_data.cam.worldtoraster;
|
|
||||||
P = transform_perspective(&tfm, sd->P);
|
|
||||||
|
|
||||||
tfm = kernel_data.cam.motion.pre;
|
|
||||||
motion_pre = transform_perspective(&tfm, motion_pre);
|
|
||||||
|
|
||||||
tfm = kernel_data.cam.motion.post;
|
|
||||||
motion_post = transform_perspective(&tfm, motion_post);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
tfm = kernel_data.cam.worldtocamera;
|
|
||||||
P = normalize(transform_point(&tfm, sd->P));
|
|
||||||
P = float2_to_float3(direction_to_panorama(kg, P));
|
|
||||||
P.x *= kernel_data.cam.width;
|
|
||||||
P.y *= kernel_data.cam.height;
|
|
||||||
|
|
||||||
tfm = kernel_data.cam.motion.pre;
|
|
||||||
motion_pre = normalize(transform_point(&tfm, motion_pre));
|
|
||||||
motion_pre = float2_to_float3(direction_to_panorama(kg, motion_pre));
|
|
||||||
motion_pre.x *= kernel_data.cam.width;
|
|
||||||
motion_pre.y *= kernel_data.cam.height;
|
|
||||||
|
|
||||||
tfm = kernel_data.cam.motion.post;
|
|
||||||
motion_post = normalize(transform_point(&tfm, motion_post));
|
|
||||||
motion_post = float2_to_float3(direction_to_panorama(kg, motion_post));
|
|
||||||
motion_post.x *= kernel_data.cam.width;
|
|
||||||
motion_post.y *= kernel_data.cam.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
motion_pre = motion_pre - P;
|
|
||||||
motion_post = P - motion_post;
|
|
||||||
|
|
||||||
return make_float4(motion_pre.x, motion_pre.y, motion_post.x, motion_post.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
__device float3 triangle_uv(KernelGlobals *kg, ShaderData *sd)
|
|
||||||
{
|
|
||||||
int offset_uv = find_attribute(kg, sd, ATTR_STD_UV);
|
|
||||||
|
|
||||||
if(offset_uv == ATTR_STD_NOT_FOUND)
|
|
||||||
return make_float3(0.0f, 0.0f, 0.0f);
|
|
||||||
|
|
||||||
float3 uv = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, offset_uv, NULL, NULL);
|
|
||||||
uv.z = 1.0f;
|
|
||||||
return uv;
|
|
||||||
}
|
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
|
||||||
|
@@ -47,6 +47,7 @@ CCL_NAMESPACE_BEGIN
|
|||||||
#define __OSL__
|
#define __OSL__
|
||||||
#endif
|
#endif
|
||||||
#define __NON_PROGRESSIVE__
|
#define __NON_PROGRESSIVE__
|
||||||
|
#define __HAIR__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __KERNEL_CUDA__
|
#ifdef __KERNEL_CUDA__
|
||||||
@@ -116,7 +117,6 @@ CCL_NAMESPACE_BEGIN
|
|||||||
#define __ANISOTROPIC__
|
#define __ANISOTROPIC__
|
||||||
#define __OBJECT_MOTION__
|
#define __OBJECT_MOTION__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//#define __SOBOL_FULL_SCREEN__
|
//#define __SOBOL_FULL_SCREEN__
|
||||||
|
|
||||||
/* Shader Evaluation */
|
/* Shader Evaluation */
|
||||||
@@ -292,7 +292,8 @@ typedef enum LightType {
|
|||||||
LIGHT_BACKGROUND,
|
LIGHT_BACKGROUND,
|
||||||
LIGHT_AREA,
|
LIGHT_AREA,
|
||||||
LIGHT_AO,
|
LIGHT_AO,
|
||||||
LIGHT_SPOT
|
LIGHT_SPOT,
|
||||||
|
LIGHT_STRAND
|
||||||
} LightType;
|
} LightType;
|
||||||
|
|
||||||
/* Camera Type */
|
/* Camera Type */
|
||||||
@@ -343,18 +344,44 @@ typedef struct Intersection {
|
|||||||
float t, u, v;
|
float t, u, v;
|
||||||
int prim;
|
int prim;
|
||||||
int object;
|
int object;
|
||||||
|
int segment;
|
||||||
} Intersection;
|
} Intersection;
|
||||||
|
|
||||||
/* Attributes */
|
/* Attributes */
|
||||||
|
|
||||||
|
#define ATTR_PRIM_TYPES 2
|
||||||
|
#define ATTR_PRIM_CURVE 1
|
||||||
|
|
||||||
typedef enum AttributeElement {
|
typedef enum AttributeElement {
|
||||||
|
ATTR_ELEMENT_NONE,
|
||||||
|
ATTR_ELEMENT_VALUE,
|
||||||
ATTR_ELEMENT_FACE,
|
ATTR_ELEMENT_FACE,
|
||||||
ATTR_ELEMENT_VERTEX,
|
ATTR_ELEMENT_VERTEX,
|
||||||
ATTR_ELEMENT_CORNER,
|
ATTR_ELEMENT_CORNER,
|
||||||
ATTR_ELEMENT_VALUE,
|
ATTR_ELEMENT_CURVE,
|
||||||
ATTR_ELEMENT_NONE
|
ATTR_ELEMENT_CURVE_KEY
|
||||||
} AttributeElement;
|
} AttributeElement;
|
||||||
|
|
||||||
|
typedef enum AttributeStandard {
|
||||||
|
ATTR_STD_NONE = 0,
|
||||||
|
ATTR_STD_VERTEX_NORMAL,
|
||||||
|
ATTR_STD_FACE_NORMAL,
|
||||||
|
ATTR_STD_UV,
|
||||||
|
ATTR_STD_UV_TANGENT,
|
||||||
|
ATTR_STD_UV_TANGENT_SIGN,
|
||||||
|
ATTR_STD_GENERATED,
|
||||||
|
ATTR_STD_POSITION_UNDEFORMED,
|
||||||
|
ATTR_STD_POSITION_UNDISPLACED,
|
||||||
|
ATTR_STD_MOTION_PRE,
|
||||||
|
ATTR_STD_MOTION_POST,
|
||||||
|
ATTR_STD_PARTICLE,
|
||||||
|
ATTR_STD_CURVE_TANGENT,
|
||||||
|
ATTR_STD_CURVE_INTERCEPT,
|
||||||
|
ATTR_STD_NUM,
|
||||||
|
|
||||||
|
ATTR_STD_NOT_FOUND = ~0
|
||||||
|
} AttributeStandard;
|
||||||
|
|
||||||
/* Closure data */
|
/* Closure data */
|
||||||
|
|
||||||
#define MAX_CLOSURE 8
|
#define MAX_CLOSURE 8
|
||||||
@@ -436,6 +463,11 @@ typedef struct ShaderData {
|
|||||||
|
|
||||||
/* primitive id if there is one, ~0 otherwise */
|
/* primitive id if there is one, ~0 otherwise */
|
||||||
int prim;
|
int prim;
|
||||||
|
|
||||||
|
#ifdef __HAIR__
|
||||||
|
/* for curves, segment number in curve, ~0 for triangles */
|
||||||
|
int segment;
|
||||||
|
#endif
|
||||||
/* parametric coordinates
|
/* parametric coordinates
|
||||||
* - barycentric weights for triangles */
|
* - barycentric weights for triangles */
|
||||||
float u, v;
|
float u, v;
|
||||||
@@ -650,6 +682,29 @@ typedef struct KernelBVH {
|
|||||||
int pad2;
|
int pad2;
|
||||||
} KernelBVH;
|
} KernelBVH;
|
||||||
|
|
||||||
|
typedef enum CurveFlag {
|
||||||
|
/* runtime flags */
|
||||||
|
CURVE_KN_BACKFACING = 1, /* backside of cylinder? */
|
||||||
|
CURVE_KN_ENCLOSEFILTER = 2, /* don't consider strands surrounding start point? */
|
||||||
|
CURVE_KN_CURVEDATA = 4, /* curve data available? */
|
||||||
|
CURVE_KN_INTERPOLATE = 8, /* render as a curve? - not supported yet */
|
||||||
|
CURVE_KN_ACCURATE = 16, /* use accurate intersections test? */
|
||||||
|
CURVE_KN_INTERSECTCORRECTION = 32, /* correct for width after determing closest midpoint? */
|
||||||
|
CURVE_KN_POSTINTERSECTCORRECTION = 64, /* correct for width after intersect? */
|
||||||
|
CURVE_KN_NORMALCORRECTION = 128, /* correct tangent normal for slope? */
|
||||||
|
CURVE_KN_TRUETANGENTGNORMAL = 256, /* use tangent normal for geometry? */
|
||||||
|
CURVE_KN_TANGENTGNORMAL = 512, /* use tangent normal for shader? */
|
||||||
|
} CurveFlag;
|
||||||
|
|
||||||
|
typedef struct KernelCurves {
|
||||||
|
/* strand intersect and normal parameters - many can be changed to flags*/
|
||||||
|
float normalmix;
|
||||||
|
float encasing_ratio;
|
||||||
|
int curveflags;
|
||||||
|
int pad;
|
||||||
|
|
||||||
|
} KernelCurves;
|
||||||
|
|
||||||
typedef struct KernelData {
|
typedef struct KernelData {
|
||||||
KernelCamera cam;
|
KernelCamera cam;
|
||||||
KernelFilm film;
|
KernelFilm film;
|
||||||
@@ -657,6 +712,7 @@ typedef struct KernelData {
|
|||||||
KernelSunSky sunsky;
|
KernelSunSky sunsky;
|
||||||
KernelIntegrator integrator;
|
KernelIntegrator integrator;
|
||||||
KernelBVH bvh;
|
KernelBVH bvh;
|
||||||
|
KernelCurves curve_kernel_data;
|
||||||
} KernelData;
|
} KernelData;
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
@@ -37,9 +37,10 @@
|
|||||||
#include "kernel_differential.h"
|
#include "kernel_differential.h"
|
||||||
#include "kernel_object.h"
|
#include "kernel_object.h"
|
||||||
#include "kernel_bvh.h"
|
#include "kernel_bvh.h"
|
||||||
#include "kernel_attribute.h"
|
|
||||||
#include "kernel_projection.h"
|
|
||||||
#include "kernel_triangle.h"
|
#include "kernel_triangle.h"
|
||||||
|
#include "kernel_curve.h"
|
||||||
|
#include "kernel_primitive.h"
|
||||||
|
#include "kernel_projection.h"
|
||||||
#include "kernel_accumulate.h"
|
#include "kernel_accumulate.h"
|
||||||
#include "kernel_shader.h"
|
#include "kernel_shader.h"
|
||||||
|
|
||||||
@@ -74,6 +75,11 @@ ustring OSLRenderServices::u_geom_numpolyvertices("geom:numpolyvertices");
|
|||||||
ustring OSLRenderServices::u_geom_trianglevertices("geom:trianglevertices");
|
ustring OSLRenderServices::u_geom_trianglevertices("geom:trianglevertices");
|
||||||
ustring OSLRenderServices::u_geom_polyvertices("geom:polyvertices");
|
ustring OSLRenderServices::u_geom_polyvertices("geom:polyvertices");
|
||||||
ustring OSLRenderServices::u_geom_name("geom:name");
|
ustring OSLRenderServices::u_geom_name("geom:name");
|
||||||
|
#ifdef __HAIR__
|
||||||
|
ustring OSLRenderServices::u_is_curve("geom:is_curve");
|
||||||
|
ustring OSLRenderServices::u_curve_thickness("geom:curve_thickness");
|
||||||
|
ustring OSLRenderServices::u_curve_tangent_normal("geom:curve_tangent_normal");
|
||||||
|
#endif
|
||||||
ustring OSLRenderServices::u_path_ray_length("path:ray_length");
|
ustring OSLRenderServices::u_path_ray_length("path:ray_length");
|
||||||
ustring OSLRenderServices::u_trace("trace");
|
ustring OSLRenderServices::u_trace("trace");
|
||||||
ustring OSLRenderServices::u_hit("hit");
|
ustring OSLRenderServices::u_hit("hit");
|
||||||
@@ -495,14 +501,14 @@ static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, const OS
|
|||||||
attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor)
|
attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor)
|
||||||
{
|
{
|
||||||
float3 fval[3];
|
float3 fval[3];
|
||||||
fval[0] = triangle_attribute_float3(kg, sd, attr.elem, attr.offset,
|
fval[0] = primitive_attribute_float3(kg, sd, attr.elem, attr.offset,
|
||||||
(derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
|
(derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
|
||||||
return set_attribute_float3(fval, type, derivatives, val);
|
return set_attribute_float3(fval, type, derivatives, val);
|
||||||
}
|
}
|
||||||
else if (attr.type == TypeDesc::TypeFloat) {
|
else if (attr.type == TypeDesc::TypeFloat) {
|
||||||
float fval[3];
|
float fval[3];
|
||||||
fval[0] = triangle_attribute_float(kg, sd, attr.elem, attr.offset,
|
fval[0] = primitive_attribute_float(kg, sd, attr.elem, attr.offset,
|
||||||
(derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
|
(derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
|
||||||
return set_attribute_float(fval, type, derivatives, val);
|
return set_attribute_float(fval, type, derivatives, val);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -593,10 +599,13 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
|
|||||||
float3 f = particle_angular_velocity(kg, particle_id);
|
float3 f = particle_angular_velocity(kg, particle_id);
|
||||||
return set_attribute_float3(f, type, derivatives, val);
|
return set_attribute_float3(f, type, derivatives, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Geometry Attributes */
|
||||||
else if (name == u_geom_numpolyvertices) {
|
else if (name == u_geom_numpolyvertices) {
|
||||||
return set_attribute_int(3, type, derivatives, val);
|
return set_attribute_int(3, type, derivatives, val);
|
||||||
}
|
}
|
||||||
else if (name == u_geom_trianglevertices || name == u_geom_polyvertices) {
|
else if ((name == u_geom_trianglevertices || name == u_geom_polyvertices)
|
||||||
|
&& sd->segment == ~0) {
|
||||||
float3 P[3];
|
float3 P[3];
|
||||||
triangle_vertices(kg, sd->prim, P);
|
triangle_vertices(kg, sd->prim, P);
|
||||||
|
|
||||||
@@ -612,6 +621,22 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
|
|||||||
ustring object_name = kg->osl->object_names[sd->object];
|
ustring object_name = kg->osl->object_names[sd->object];
|
||||||
return set_attribute_string(object_name, type, derivatives, val);
|
return set_attribute_string(object_name, type, derivatives, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __HAIR__
|
||||||
|
/* Hair Attributes */
|
||||||
|
else if (name == u_is_curve) {
|
||||||
|
float f = (sd->segment != ~0);
|
||||||
|
return set_attribute_float(f, type, derivatives, val);
|
||||||
|
}
|
||||||
|
else if (name == u_curve_thickness) {
|
||||||
|
float f = curve_thickness(kg, sd);
|
||||||
|
return set_attribute_float(f, type, derivatives, val);
|
||||||
|
}
|
||||||
|
else if (name == u_curve_tangent_normal) {
|
||||||
|
float3 f = curve_tangent_normal(kg, sd);
|
||||||
|
return set_attribute_float3(f, type, derivatives, val);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -634,7 +659,7 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
|
|||||||
{
|
{
|
||||||
KernelGlobals *kg = kernel_globals;
|
KernelGlobals *kg = kernel_globals;
|
||||||
ShaderData *sd = (ShaderData *)renderstate;
|
ShaderData *sd = (ShaderData *)renderstate;
|
||||||
int object, tri;
|
int object, prim, segment;
|
||||||
|
|
||||||
/* lookup of attribute on another object */
|
/* lookup of attribute on another object */
|
||||||
if (object_name != u_empty || sd == NULL) {
|
if (object_name != u_empty || sd == NULL) {
|
||||||
@@ -644,17 +669,20 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
object = it->second;
|
object = it->second;
|
||||||
tri = ~0;
|
prim = ~0;
|
||||||
|
segment = ~0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
object = sd->object;
|
object = sd->object;
|
||||||
tri = sd->prim;
|
prim = sd->prim;
|
||||||
|
segment = sd->segment;
|
||||||
|
|
||||||
if (object == ~0)
|
if (object == ~0)
|
||||||
return get_background_attribute(kg, sd, name, type, derivatives, val);
|
return get_background_attribute(kg, sd, name, type, derivatives, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find attribute on object */
|
/* find attribute on object */
|
||||||
|
object = object*ATTR_PRIM_TYPES + (segment != ~0);
|
||||||
OSLGlobals::AttributeMap& attribute_map = kg->osl->attribute_map[object];
|
OSLGlobals::AttributeMap& attribute_map = kg->osl->attribute_map[object];
|
||||||
OSLGlobals::AttributeMap::iterator it = attribute_map.find(name);
|
OSLGlobals::AttributeMap::iterator it = attribute_map.find(name);
|
||||||
|
|
||||||
@@ -663,7 +691,7 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
|
|||||||
|
|
||||||
if (attr.elem != ATTR_ELEMENT_VALUE) {
|
if (attr.elem != ATTR_ELEMENT_VALUE) {
|
||||||
/* triangle and vertex attributes */
|
/* triangle and vertex attributes */
|
||||||
if (tri != ~0)
|
if (prim != ~0)
|
||||||
return get_mesh_attribute(kg, sd, attr, type, derivatives, val);
|
return get_mesh_attribute(kg, sd, attr, type, derivatives, val);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@@ -130,6 +130,9 @@ public:
|
|||||||
static ustring u_geom_trianglevertices;
|
static ustring u_geom_trianglevertices;
|
||||||
static ustring u_geom_polyvertices;
|
static ustring u_geom_polyvertices;
|
||||||
static ustring u_geom_name;
|
static ustring u_geom_name;
|
||||||
|
static ustring u_is_curve;
|
||||||
|
static ustring u_curve_thickness;
|
||||||
|
static ustring u_curve_tangent_normal;
|
||||||
static ustring u_path_ray_length;
|
static ustring u_path_ray_length;
|
||||||
static ustring u_trace;
|
static ustring u_trace;
|
||||||
static ustring u_hit;
|
static ustring u_hit;
|
||||||
|
@@ -26,9 +26,10 @@
|
|||||||
#include "osl_services.h"
|
#include "osl_services.h"
|
||||||
#include "osl_shader.h"
|
#include "osl_shader.h"
|
||||||
|
|
||||||
#include "util_attribute.h"
|
|
||||||
#include "util_foreach.h"
|
#include "util_foreach.h"
|
||||||
|
|
||||||
|
#include "attribute.h"
|
||||||
|
|
||||||
#include <OSL/oslexec.h>
|
#include <OSL/oslexec.h>
|
||||||
|
|
||||||
CCL_NAMESPACE_BEGIN
|
CCL_NAMESPACE_BEGIN
|
||||||
@@ -453,15 +454,17 @@ float3 OSLShader::volume_eval_phase(const ShaderClosure *sc, const float3 omega_
|
|||||||
|
|
||||||
/* Attributes */
|
/* Attributes */
|
||||||
|
|
||||||
int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id)
|
int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem)
|
||||||
{
|
{
|
||||||
/* for OSL, a hash map is used to lookup the attribute by name. */
|
/* for OSL, a hash map is used to lookup the attribute by name. */
|
||||||
OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[sd->object];
|
int object = sd->object*ATTR_PRIM_TYPES + (sd->segment != ~0);
|
||||||
ustring stdname(std::string("std::") + std::string(attribute_standard_name((AttributeStandard)id)));
|
OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[object];
|
||||||
|
ustring stdname(std::string("geom:") + std::string(Attribute::standard_name((AttributeStandard)id)));
|
||||||
OSLGlobals::AttributeMap::const_iterator it = attr_map.find(stdname);
|
OSLGlobals::AttributeMap::const_iterator it = attr_map.find(stdname);
|
||||||
|
|
||||||
if (it != attr_map.end()) {
|
if (it != attr_map.end()) {
|
||||||
const OSLGlobals::Attribute &osl_attr = it->second;
|
const OSLGlobals::Attribute &osl_attr = it->second;
|
||||||
|
*elem = osl_attr.elem;
|
||||||
/* return result */
|
/* return result */
|
||||||
return (osl_attr.elem == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : osl_attr.offset;
|
return (osl_attr.elem == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : osl_attr.offset;
|
||||||
}
|
}
|
||||||
|
@@ -74,7 +74,7 @@ public:
|
|||||||
const float3 omega_in, const float3 omega_out);
|
const float3 omega_in, const float3 omega_out);
|
||||||
|
|
||||||
/* attributes */
|
/* attributes */
|
||||||
static int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id);
|
static int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem);
|
||||||
};
|
};
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
@@ -27,6 +27,7 @@ set(SRC_OSL
|
|||||||
node_glass_bsdf.osl
|
node_glass_bsdf.osl
|
||||||
node_glossy_bsdf.osl
|
node_glossy_bsdf.osl
|
||||||
node_gradient_texture.osl
|
node_gradient_texture.osl
|
||||||
|
node_hair_info.osl
|
||||||
node_holdout.osl
|
node_holdout.osl
|
||||||
node_hsv.osl
|
node_hsv.osl
|
||||||
node_image_texture.osl
|
node_image_texture.osl
|
||||||
|
32
intern/cycles/kernel/shaders/node_hair_info.osl
Normal file
32
intern/cycles/kernel/shaders/node_hair_info.osl
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Blender Foundation.
|
||||||
|
*
|
||||||
|
* 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 2
|
||||||
|
* 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, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdosl.h"
|
||||||
|
|
||||||
|
shader node_hair_info(
|
||||||
|
output float IsStrand = 0.0,
|
||||||
|
output float Intercept = 0.0,
|
||||||
|
output float Thickness = 0.0,
|
||||||
|
output normal TangentNormal = N)
|
||||||
|
{
|
||||||
|
getattribute("geom:is_curve", IsStrand);
|
||||||
|
getattribute("geom:curve_intercept", Intercept);
|
||||||
|
getattribute("geom:curve_thickness", Thickness);
|
||||||
|
getattribute("geom:curve_tangent_normal", TangentNormal);
|
||||||
|
}
|
||||||
|
|
@@ -161,6 +161,15 @@ vector cross (vector a, vector b) BUILTIN;
|
|||||||
float dot (vector a, vector b) BUILTIN;
|
float dot (vector a, vector b) BUILTIN;
|
||||||
float length (vector v) BUILTIN;
|
float length (vector v) BUILTIN;
|
||||||
float distance (point a, point b) BUILTIN;
|
float distance (point a, point b) BUILTIN;
|
||||||
|
float distance (point a, point b, point q)
|
||||||
|
{
|
||||||
|
vector d = b - a;
|
||||||
|
float dd = dot(d, d);
|
||||||
|
if(dd == 0.0)
|
||||||
|
return distance(q, a);
|
||||||
|
float t = dot(q - a, d)/dd;
|
||||||
|
return distance(q, a + clamp(t, 0.0, 1.0)*d);
|
||||||
|
}
|
||||||
normal normalize (normal v) BUILTIN;
|
normal normalize (normal v) BUILTIN;
|
||||||
vector normalize (vector v) BUILTIN;
|
vector normalize (vector v) BUILTIN;
|
||||||
vector faceforward (vector N, vector I, vector Nref) BUILTIN;
|
vector faceforward (vector N, vector I, vector Nref) BUILTIN;
|
||||||
@@ -304,7 +313,7 @@ color transformc (string to, color x)
|
|||||||
r = color (dot (vector(0.299, 0.587, 0.114), (vector)x),
|
r = color (dot (vector(0.299, 0.587, 0.114), (vector)x),
|
||||||
dot (vector(0.596, -0.275, -0.321), (vector)x),
|
dot (vector(0.596, -0.275, -0.321), (vector)x),
|
||||||
dot (vector(0.212, -0.523, 0.311), (vector)x));
|
dot (vector(0.212, -0.523, 0.311), (vector)x));
|
||||||
else if (to == "xyz")
|
else if (to == "XYZ")
|
||||||
r = color (dot (vector(0.412453, 0.357580, 0.180423), (vector)x),
|
r = color (dot (vector(0.412453, 0.357580, 0.180423), (vector)x),
|
||||||
dot (vector(0.212671, 0.715160, 0.072169), (vector)x),
|
dot (vector(0.212671, 0.715160, 0.072169), (vector)x),
|
||||||
dot (vector(0.019334, 0.119193, 0.950227), (vector)x));
|
dot (vector(0.019334, 0.119193, 0.950227), (vector)x));
|
||||||
@@ -366,7 +375,7 @@ color transformc (string from, string to, color x)
|
|||||||
r = color (dot (vector(1, 0.9557, 0.6199), (vector)x),
|
r = color (dot (vector(1, 0.9557, 0.6199), (vector)x),
|
||||||
dot (vector(1, -0.2716, -0.6469), (vector)x),
|
dot (vector(1, -0.2716, -0.6469), (vector)x),
|
||||||
dot (vector(1, -1.1082, 1.7051), (vector)x));
|
dot (vector(1, -1.1082, 1.7051), (vector)x));
|
||||||
else if (from == "xyz")
|
else if (from == "XYZ")
|
||||||
r = color (dot (vector( 3.240479, -1.537150, -0.498535), (vector)x),
|
r = color (dot (vector( 3.240479, -1.537150, -0.498535), (vector)x),
|
||||||
dot (vector(-0.969256, 1.875991, 0.041556), (vector)x),
|
dot (vector(-0.969256, 1.875991, 0.041556), (vector)x),
|
||||||
dot (vector( 0.055648, -0.204043, 1.057311), (vector)x));
|
dot (vector( 0.055648, -0.204043, 1.057311), (vector)x));
|
||||||
@@ -409,6 +418,8 @@ int startswith (string s, string prefix) BUILTIN;
|
|||||||
int endswith (string s, string suffix) BUILTIN;
|
int endswith (string s, string suffix) BUILTIN;
|
||||||
string substr (string s, int start, int len) BUILTIN;
|
string substr (string s, int start, int len) BUILTIN;
|
||||||
string substr (string s, int start) { return substr (s, start, strlen(s)); }
|
string substr (string s, int start) { return substr (s, start, strlen(s)); }
|
||||||
|
float strtof (string str) BUILTIN;
|
||||||
|
int strtoi (string str) BUILTIN;
|
||||||
|
|
||||||
// Define concat in terms of shorter concat
|
// Define concat in terms of shorter concat
|
||||||
string concat (string a, string b, string c) {
|
string concat (string a, string b, string c) {
|
||||||
|
@@ -301,6 +301,12 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
|
|||||||
case NODE_PARTICLE_INFO:
|
case NODE_PARTICLE_INFO:
|
||||||
svm_node_particle_info(kg, sd, stack, node.y, node.z);
|
svm_node_particle_info(kg, sd, stack, node.y, node.z);
|
||||||
break;
|
break;
|
||||||
|
#ifdef __HAIR__
|
||||||
|
case NODE_HAIR_INFO:
|
||||||
|
svm_node_hair_info(kg, sd, stack, node.y, node.z);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
case NODE_CONVERT:
|
case NODE_CONVERT:
|
||||||
svm_node_convert(sd, stack, node.y, node.z, node.w);
|
svm_node_convert(sd, stack, node.y, node.z, node.w);
|
||||||
|
@@ -28,10 +28,15 @@ __device void svm_node_attr_init(KernelGlobals *kg, ShaderData *sd,
|
|||||||
/* find attribute by unique id */
|
/* find attribute by unique id */
|
||||||
uint id = node.y;
|
uint id = node.y;
|
||||||
uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
|
uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
|
||||||
|
#ifdef __HAIR__
|
||||||
|
attr_offset = (sd->segment == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE;
|
||||||
|
#endif
|
||||||
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
|
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
|
||||||
|
|
||||||
while(attr_map.x != id)
|
while(attr_map.x != id) {
|
||||||
attr_map = kernel_tex_fetch(__attributes_map, ++attr_offset);
|
attr_offset += ATTR_PRIM_TYPES;
|
||||||
|
attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
|
||||||
|
}
|
||||||
|
|
||||||
/* return result */
|
/* return result */
|
||||||
*elem = (AttributeElement)attr_map.y;
|
*elem = (AttributeElement)attr_map.y;
|
||||||
@@ -61,21 +66,21 @@ __device void svm_node_attr(KernelGlobals *kg, ShaderData *sd, float *stack, uin
|
|||||||
/* fetch and store attribute */
|
/* fetch and store attribute */
|
||||||
if(type == NODE_ATTR_FLOAT) {
|
if(type == NODE_ATTR_FLOAT) {
|
||||||
if(mesh_type == NODE_ATTR_FLOAT) {
|
if(mesh_type == NODE_ATTR_FLOAT) {
|
||||||
float f = triangle_attribute_float(kg, sd, elem, offset, NULL, NULL);
|
float f = primitive_attribute_float(kg, sd, elem, offset, NULL, NULL);
|
||||||
stack_store_float(stack, out_offset, f);
|
stack_store_float(stack, out_offset, f);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, NULL);
|
float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL);
|
||||||
stack_store_float(stack, out_offset, average(f));
|
stack_store_float(stack, out_offset, average(f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(mesh_type == NODE_ATTR_FLOAT3) {
|
if(mesh_type == NODE_ATTR_FLOAT3) {
|
||||||
float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, NULL);
|
float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL);
|
||||||
stack_store_float3(stack, out_offset, f);
|
stack_store_float3(stack, out_offset, f);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
float f = triangle_attribute_float(kg, sd, elem, offset, NULL, NULL);
|
float f = primitive_attribute_float(kg, sd, elem, offset, NULL, NULL);
|
||||||
stack_store_float3(stack, out_offset, make_float3(f, f, f));
|
stack_store_float3(stack, out_offset, make_float3(f, f, f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,24 +99,24 @@ __device void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *st
|
|||||||
if(type == NODE_ATTR_FLOAT) {
|
if(type == NODE_ATTR_FLOAT) {
|
||||||
if(mesh_type == NODE_ATTR_FLOAT) {
|
if(mesh_type == NODE_ATTR_FLOAT) {
|
||||||
float dx;
|
float dx;
|
||||||
float f = triangle_attribute_float(kg, sd, elem, offset, &dx, NULL);
|
float f = primitive_attribute_float(kg, sd, elem, offset, &dx, NULL);
|
||||||
stack_store_float(stack, out_offset, f+dx);
|
stack_store_float(stack, out_offset, f+dx);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
float3 dx;
|
float3 dx;
|
||||||
float3 f = triangle_attribute_float3(kg, sd, elem, offset, &dx, NULL);
|
float3 f = primitive_attribute_float3(kg, sd, elem, offset, &dx, NULL);
|
||||||
stack_store_float(stack, out_offset, average(f+dx));
|
stack_store_float(stack, out_offset, average(f+dx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(mesh_type == NODE_ATTR_FLOAT3) {
|
if(mesh_type == NODE_ATTR_FLOAT3) {
|
||||||
float3 dx;
|
float3 dx;
|
||||||
float3 f = triangle_attribute_float3(kg, sd, elem, offset, &dx, NULL);
|
float3 f = primitive_attribute_float3(kg, sd, elem, offset, &dx, NULL);
|
||||||
stack_store_float3(stack, out_offset, f+dx);
|
stack_store_float3(stack, out_offset, f+dx);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
float dx;
|
float dx;
|
||||||
float f = triangle_attribute_float(kg, sd, elem, offset, &dx, NULL);
|
float f = primitive_attribute_float(kg, sd, elem, offset, &dx, NULL);
|
||||||
stack_store_float3(stack, out_offset, make_float3(f+dx, f+dx, f+dx));
|
stack_store_float3(stack, out_offset, make_float3(f+dx, f+dx, f+dx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,24 +135,24 @@ __device void svm_node_attr_bump_dy(KernelGlobals *kg, ShaderData *sd, float *st
|
|||||||
if(type == NODE_ATTR_FLOAT) {
|
if(type == NODE_ATTR_FLOAT) {
|
||||||
if(mesh_type == NODE_ATTR_FLOAT) {
|
if(mesh_type == NODE_ATTR_FLOAT) {
|
||||||
float dy;
|
float dy;
|
||||||
float f = triangle_attribute_float(kg, sd, elem, offset, NULL, &dy);
|
float f = primitive_attribute_float(kg, sd, elem, offset, NULL, &dy);
|
||||||
stack_store_float(stack, out_offset, f+dy);
|
stack_store_float(stack, out_offset, f+dy);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
float3 dy;
|
float3 dy;
|
||||||
float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, &dy);
|
float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, &dy);
|
||||||
stack_store_float(stack, out_offset, average(f+dy));
|
stack_store_float(stack, out_offset, average(f+dy));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(mesh_type == NODE_ATTR_FLOAT3) {
|
if(mesh_type == NODE_ATTR_FLOAT3) {
|
||||||
float3 dy;
|
float3 dy;
|
||||||
float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, &dy);
|
float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, &dy);
|
||||||
stack_store_float3(stack, out_offset, f+dy);
|
stack_store_float3(stack, out_offset, f+dy);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
float dy;
|
float dy;
|
||||||
float f = triangle_attribute_float(kg, sd, elem, offset, NULL, &dy);
|
float f = primitive_attribute_float(kg, sd, elem, offset, NULL, &dy);
|
||||||
stack_store_float3(stack, out_offset, make_float3(f+dy, f+dy, f+dy));
|
stack_store_float3(stack, out_offset, make_float3(f+dy, f+dy, f+dy));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,23 +28,7 @@ __device void svm_node_geometry(KernelGlobals *kg, ShaderData *sd, float *stack,
|
|||||||
case NODE_GEOM_P: data = sd->P; break;
|
case NODE_GEOM_P: data = sd->P; break;
|
||||||
case NODE_GEOM_N: data = sd->N; break;
|
case NODE_GEOM_N: data = sd->N; break;
|
||||||
#ifdef __DPDU__
|
#ifdef __DPDU__
|
||||||
case NODE_GEOM_T: {
|
case NODE_GEOM_T: data = primitive_tangent(kg, sd); break;
|
||||||
/* try to create spherical tangent from generated coordinates */
|
|
||||||
int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_GENERATED): ATTR_STD_NOT_FOUND;
|
|
||||||
|
|
||||||
if(attr_offset != ATTR_STD_NOT_FOUND) {
|
|
||||||
data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL);
|
|
||||||
data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f);
|
|
||||||
object_normal_transform(kg, sd, &data);
|
|
||||||
data = cross(sd->N, normalize(cross(data, sd->N)));;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* otherwise use surface derivatives */
|
|
||||||
data = normalize(sd->dPdu);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
case NODE_GEOM_I: data = sd->I; break;
|
case NODE_GEOM_I: data = sd->I; break;
|
||||||
case NODE_GEOM_Ng: data = sd->Ng; break;
|
case NODE_GEOM_Ng: data = sd->Ng; break;
|
||||||
@@ -160,5 +144,36 @@ __device void svm_node_particle_info(KernelGlobals *kg, ShaderData *sd, float *s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __HAIR__
|
||||||
|
|
||||||
|
/* Hair Info */
|
||||||
|
|
||||||
|
__device void svm_node_hair_info(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
|
||||||
|
{
|
||||||
|
float data;
|
||||||
|
float3 data3;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case NODE_INFO_CURVE_IS_STRAND: {
|
||||||
|
data = (sd->segment != ~0);
|
||||||
|
stack_store_float(stack, out_offset, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NODE_INFO_CURVE_INTERCEPT:
|
||||||
|
break; /* handled as attribute */
|
||||||
|
case NODE_INFO_CURVE_THICKNESS: {
|
||||||
|
data = curve_thickness(kg, sd);
|
||||||
|
stack_store_float(stack, out_offset, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NODE_INFO_CURVE_TANGENT_NORMAL: {
|
||||||
|
data3 = curve_tangent_normal(kg, sd);
|
||||||
|
stack_store_float3(stack, out_offset, data3);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
|
||||||
|
@@ -248,8 +248,9 @@ __device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stac
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* first try to get tangent attribute */
|
/* first try to get tangent attribute */
|
||||||
int attr_offset = find_attribute(kg, sd, node.z);
|
AttributeElement attr_elem, attr_sign_elem;
|
||||||
int attr_sign_offset = find_attribute(kg, sd, node.w);
|
int attr_offset = find_attribute(kg, sd, node.z, &attr_elem);
|
||||||
|
int attr_sign_offset = find_attribute(kg, sd, node.w, &attr_sign_elem);
|
||||||
|
|
||||||
if(attr_offset == ATTR_STD_NOT_FOUND || attr_sign_offset == ATTR_STD_NOT_FOUND) {
|
if(attr_offset == ATTR_STD_NOT_FOUND || attr_sign_offset == ATTR_STD_NOT_FOUND) {
|
||||||
stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
|
stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
|
||||||
@@ -257,8 +258,8 @@ __device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stac
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ensure orthogonal and normalized (interpolation breaks it) */
|
/* ensure orthogonal and normalized (interpolation breaks it) */
|
||||||
float3 tangent = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL);
|
float3 tangent = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
|
||||||
float sign = triangle_attribute_float(kg, sd, ATTR_ELEMENT_CORNER, attr_sign_offset, NULL, NULL);
|
float sign = primitive_attribute_float(kg, sd, attr_sign_elem, attr_sign_offset, NULL, NULL);
|
||||||
|
|
||||||
object_normal_transform(kg, sd, &tangent);
|
object_normal_transform(kg, sd, &tangent);
|
||||||
tangent = cross(sd->N, normalize(cross(tangent, sd->N)));;
|
tangent = cross(sd->N, normalize(cross(tangent, sd->N)));;
|
||||||
@@ -295,22 +296,24 @@ __device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack,
|
|||||||
|
|
||||||
if(direction_type == NODE_TANGENT_UVMAP) {
|
if(direction_type == NODE_TANGENT_UVMAP) {
|
||||||
/* UV map */
|
/* UV map */
|
||||||
int attr_offset = find_attribute(kg, sd, node.z);
|
AttributeElement attr_elem;
|
||||||
|
int attr_offset = find_attribute(kg, sd, node.z, &attr_elem);
|
||||||
|
|
||||||
if(attr_offset == ATTR_STD_NOT_FOUND)
|
if(attr_offset == ATTR_STD_NOT_FOUND)
|
||||||
tangent = make_float3(0.0f, 0.0f, 0.0f);
|
tangent = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
else
|
else
|
||||||
tangent = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL);
|
tangent = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* radial */
|
/* radial */
|
||||||
int attr_offset = find_attribute(kg, sd, node.z);
|
AttributeElement attr_elem;
|
||||||
|
int attr_offset = find_attribute(kg, sd, node.z, &attr_elem);
|
||||||
float3 generated;
|
float3 generated;
|
||||||
|
|
||||||
if(attr_offset == ATTR_STD_NOT_FOUND)
|
if(attr_offset == ATTR_STD_NOT_FOUND)
|
||||||
generated = sd->P;
|
generated = sd->P;
|
||||||
else
|
else
|
||||||
generated = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL);
|
generated = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
|
||||||
|
|
||||||
if(axis == NODE_TANGENT_AXIS_X)
|
if(axis == NODE_TANGENT_AXIS_X)
|
||||||
tangent = make_float3(0.0f, -(generated.z - 0.5f), (generated.y - 0.5f));
|
tangent = make_float3(0.0f, -(generated.z - 0.5f), (generated.y - 0.5f));
|
||||||
|
@@ -97,7 +97,8 @@ typedef enum NodeType {
|
|||||||
NODE_CLOSURE_SET_NORMAL,
|
NODE_CLOSURE_SET_NORMAL,
|
||||||
NODE_CLOSURE_AMBIENT_OCCLUSION,
|
NODE_CLOSURE_AMBIENT_OCCLUSION,
|
||||||
NODE_TANGENT,
|
NODE_TANGENT,
|
||||||
NODE_NORMAL_MAP
|
NODE_NORMAL_MAP,
|
||||||
|
NODE_HAIR_INFO
|
||||||
} NodeType;
|
} NodeType;
|
||||||
|
|
||||||
typedef enum NodeAttributeType {
|
typedef enum NodeAttributeType {
|
||||||
@@ -132,6 +133,13 @@ typedef enum NodeParticleInfo {
|
|||||||
NODE_INFO_PAR_ANGULAR_VELOCITY
|
NODE_INFO_PAR_ANGULAR_VELOCITY
|
||||||
} NodeParticleInfo;
|
} NodeParticleInfo;
|
||||||
|
|
||||||
|
typedef enum NodeHairInfo {
|
||||||
|
NODE_INFO_CURVE_IS_STRAND,
|
||||||
|
NODE_INFO_CURVE_INTERCEPT,
|
||||||
|
NODE_INFO_CURVE_THICKNESS,
|
||||||
|
NODE_INFO_CURVE_TANGENT_NORMAL
|
||||||
|
} NodeHairInfo;
|
||||||
|
|
||||||
typedef enum NodeLightPath {
|
typedef enum NodeLightPath {
|
||||||
NODE_LP_camera = 0,
|
NODE_LP_camera = 0,
|
||||||
NODE_LP_shadow,
|
NODE_LP_shadow,
|
||||||
|
@@ -31,6 +31,7 @@ set(SRC
|
|||||||
object.cpp
|
object.cpp
|
||||||
osl.cpp
|
osl.cpp
|
||||||
particles.cpp
|
particles.cpp
|
||||||
|
curves.cpp
|
||||||
scene.cpp
|
scene.cpp
|
||||||
session.cpp
|
session.cpp
|
||||||
shader.cpp
|
shader.cpp
|
||||||
@@ -56,6 +57,7 @@ set(SRC_HEADERS
|
|||||||
object.h
|
object.h
|
||||||
osl.h
|
osl.h
|
||||||
particles.h
|
particles.h
|
||||||
|
curves.h
|
||||||
scene.h
|
scene.h
|
||||||
session.h
|
session.h
|
||||||
shader.h
|
shader.h
|
||||||
|
@@ -26,7 +26,7 @@ CCL_NAMESPACE_BEGIN
|
|||||||
|
|
||||||
/* Attribute */
|
/* Attribute */
|
||||||
|
|
||||||
void Attribute::set(ustring name_, TypeDesc type_, Element element_)
|
void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_)
|
||||||
{
|
{
|
||||||
name = name_;
|
name = name_;
|
||||||
type = type_;
|
type = type_;
|
||||||
@@ -39,12 +39,30 @@ void Attribute::set(ustring name_, TypeDesc type_, Element element_)
|
|||||||
type == TypeDesc::TypeNormal);
|
type == TypeDesc::TypeNormal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attribute::reserve(int numverts, int numtris)
|
void Attribute::reserve(int numverts, int numtris, int numcurves, int numkeys)
|
||||||
{
|
{
|
||||||
buffer.resize(buffer_size(numverts, numtris), 0);
|
buffer.resize(buffer_size(numverts, numtris, numcurves, numkeys), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Attribute::data_sizeof()
|
void Attribute::add(const float& f)
|
||||||
|
{
|
||||||
|
char *data = (char*)&f;
|
||||||
|
size_t size = sizeof(f);
|
||||||
|
|
||||||
|
for(size_t i = 0; i < size; i++)
|
||||||
|
buffer.push_back(data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Attribute::add(const float3& f)
|
||||||
|
{
|
||||||
|
char *data = (char*)&f;
|
||||||
|
size_t size = sizeof(f);
|
||||||
|
|
||||||
|
for(size_t i = 0; i < size; i++)
|
||||||
|
buffer.push_back(data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Attribute::data_sizeof() const
|
||||||
{
|
{
|
||||||
if(type == TypeDesc::TypeFloat)
|
if(type == TypeDesc::TypeFloat)
|
||||||
return sizeof(float);
|
return sizeof(float);
|
||||||
@@ -52,19 +70,27 @@ size_t Attribute::data_sizeof()
|
|||||||
return sizeof(float3);
|
return sizeof(float3);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Attribute::element_size(int numverts, int numtris)
|
size_t Attribute::element_size(int numverts, int numtris, int numcurves, int numkeys) const
|
||||||
{
|
{
|
||||||
if(element == VERTEX)
|
if(element == ATTR_ELEMENT_VALUE)
|
||||||
|
return 1;
|
||||||
|
if(element == ATTR_ELEMENT_VERTEX)
|
||||||
return numverts;
|
return numverts;
|
||||||
else if(element == FACE)
|
else if(element == ATTR_ELEMENT_FACE)
|
||||||
return numtris;
|
return numtris;
|
||||||
else
|
else if(element == ATTR_ELEMENT_CORNER)
|
||||||
return numtris*3;
|
return numtris*3;
|
||||||
|
else if(element == ATTR_ELEMENT_CURVE)
|
||||||
|
return numcurves;
|
||||||
|
else if(element == ATTR_ELEMENT_CURVE_KEY)
|
||||||
|
return numkeys;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Attribute::buffer_size(int numverts, int numtris)
|
size_t Attribute::buffer_size(int numverts, int numtris, int numcurves, int numkeys) const
|
||||||
{
|
{
|
||||||
return element_size(numverts, numtris)*data_sizeof();
|
return element_size(numverts, numtris, numcurves, numkeys)*data_sizeof();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Attribute::same_storage(TypeDesc a, TypeDesc b)
|
bool Attribute::same_storage(TypeDesc a, TypeDesc b)
|
||||||
@@ -84,18 +110,51 @@ bool Attribute::same_storage(TypeDesc a, TypeDesc b)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *Attribute::standard_name(AttributeStandard std)
|
||||||
|
{
|
||||||
|
if(std == ATTR_STD_VERTEX_NORMAL)
|
||||||
|
return "N";
|
||||||
|
else if(std == ATTR_STD_FACE_NORMAL)
|
||||||
|
return "Ng";
|
||||||
|
else if(std == ATTR_STD_UV)
|
||||||
|
return "uv";
|
||||||
|
else if(std == ATTR_STD_GENERATED)
|
||||||
|
return "generated";
|
||||||
|
else if(std == ATTR_STD_UV_TANGENT)
|
||||||
|
return "tangent";
|
||||||
|
else if(std == ATTR_STD_UV_TANGENT_SIGN)
|
||||||
|
return "tangent_sign";
|
||||||
|
else if(std == ATTR_STD_POSITION_UNDEFORMED)
|
||||||
|
return "undeformed";
|
||||||
|
else if(std == ATTR_STD_POSITION_UNDISPLACED)
|
||||||
|
return "undisplaced";
|
||||||
|
else if(std == ATTR_STD_MOTION_PRE)
|
||||||
|
return "motion_pre";
|
||||||
|
else if(std == ATTR_STD_MOTION_POST)
|
||||||
|
return "motion_post";
|
||||||
|
else if(std == ATTR_STD_PARTICLE)
|
||||||
|
return "particle";
|
||||||
|
else if(std == ATTR_STD_CURVE_TANGENT)
|
||||||
|
return "curve_tangent";
|
||||||
|
else if(std == ATTR_STD_CURVE_INTERCEPT)
|
||||||
|
return "curve_intercept";
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
/* Attribute Set */
|
/* Attribute Set */
|
||||||
|
|
||||||
AttributeSet::AttributeSet()
|
AttributeSet::AttributeSet()
|
||||||
{
|
{
|
||||||
mesh = NULL;
|
triangle_mesh = NULL;
|
||||||
|
curve_mesh = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
AttributeSet::~AttributeSet()
|
AttributeSet::~AttributeSet()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Attribute *AttributeSet::add(ustring name, TypeDesc type, Attribute::Element element)
|
Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement element)
|
||||||
{
|
{
|
||||||
Attribute *attr = find(name);
|
Attribute *attr = find(name);
|
||||||
|
|
||||||
@@ -111,24 +170,22 @@ Attribute *AttributeSet::add(ustring name, TypeDesc type, Attribute::Element ele
|
|||||||
attributes.push_back(Attribute());
|
attributes.push_back(Attribute());
|
||||||
attr = &attributes.back();
|
attr = &attributes.back();
|
||||||
|
|
||||||
if(element == Attribute::VERTEX)
|
attr->set(name, type, element);
|
||||||
attr->set(name, type, element);
|
|
||||||
else if(element == Attribute::FACE)
|
|
||||||
attr->set(name, type, element);
|
|
||||||
else if(element == Attribute::CORNER)
|
|
||||||
attr->set(name, type, element);
|
|
||||||
|
|
||||||
if(mesh)
|
/* this is weak .. */
|
||||||
attr->reserve(mesh->verts.size(), mesh->triangles.size());
|
if(triangle_mesh)
|
||||||
|
attr->reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), 0, 0);
|
||||||
|
if(curve_mesh)
|
||||||
|
attr->reserve(0, 0, curve_mesh->curves.size(), curve_mesh->curve_keys.size());
|
||||||
|
|
||||||
return attr;
|
return attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Attribute *AttributeSet::find(ustring name)
|
Attribute *AttributeSet::find(ustring name) const
|
||||||
{
|
{
|
||||||
foreach(Attribute& attr, attributes)
|
foreach(const Attribute& attr, attributes)
|
||||||
if(attr.name == name)
|
if(attr.name == name)
|
||||||
return &attr;
|
return (Attribute*)&attr;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -154,41 +211,59 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
|
|||||||
Attribute *attr = NULL;
|
Attribute *attr = NULL;
|
||||||
|
|
||||||
if(name == ustring())
|
if(name == ustring())
|
||||||
name = attribute_standard_name(std);
|
name = Attribute::standard_name(std);
|
||||||
|
|
||||||
if(std == ATTR_STD_VERTEX_NORMAL)
|
if(triangle_mesh) {
|
||||||
attr = add(name, TypeDesc::TypeNormal, Attribute::VERTEX);
|
if(std == ATTR_STD_VERTEX_NORMAL)
|
||||||
else if(std == ATTR_STD_FACE_NORMAL)
|
attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
|
||||||
attr = add(name, TypeDesc::TypeNormal, Attribute::FACE);
|
else if(std == ATTR_STD_FACE_NORMAL)
|
||||||
else if(std == ATTR_STD_UV)
|
attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_FACE);
|
||||||
attr = add(name, TypeDesc::TypePoint, Attribute::CORNER);
|
else if(std == ATTR_STD_UV)
|
||||||
else if(std == ATTR_STD_UV_TANGENT)
|
attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
|
||||||
attr = add(name, TypeDesc::TypeVector, Attribute::CORNER);
|
else if(std == ATTR_STD_UV_TANGENT)
|
||||||
else if(std == ATTR_STD_UV_TANGENT_SIGN)
|
attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
|
||||||
attr = add(name, TypeDesc::TypeFloat, Attribute::CORNER);
|
else if(std == ATTR_STD_UV_TANGENT_SIGN)
|
||||||
else if(std == ATTR_STD_GENERATED)
|
attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
|
||||||
attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
|
else if(std == ATTR_STD_GENERATED)
|
||||||
else if(std == ATTR_STD_POSITION_UNDEFORMED)
|
attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
|
||||||
attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
|
else if(std == ATTR_STD_POSITION_UNDEFORMED)
|
||||||
else if(std == ATTR_STD_POSITION_UNDISPLACED)
|
attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
|
||||||
attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
|
else if(std == ATTR_STD_POSITION_UNDISPLACED)
|
||||||
else if(std == ATTR_STD_MOTION_PRE)
|
attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
|
||||||
attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
|
else if(std == ATTR_STD_MOTION_PRE)
|
||||||
else if(std == ATTR_STD_MOTION_POST)
|
attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
|
||||||
attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
|
else if(std == ATTR_STD_MOTION_POST)
|
||||||
else
|
attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
|
||||||
assert(0);
|
else
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
else if(curve_mesh) {
|
||||||
|
if(std == ATTR_STD_UV)
|
||||||
|
attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
|
||||||
|
else if(std == ATTR_STD_GENERATED)
|
||||||
|
attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
|
||||||
|
else if(std == ATTR_STD_MOTION_PRE)
|
||||||
|
attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY);
|
||||||
|
else if(std == ATTR_STD_MOTION_POST)
|
||||||
|
attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY);
|
||||||
|
else if(std == ATTR_STD_CURVE_TANGENT)
|
||||||
|
attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CURVE_KEY);
|
||||||
|
else if(std == ATTR_STD_CURVE_INTERCEPT)
|
||||||
|
attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY);
|
||||||
|
else
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
attr->std = std;
|
attr->std = std;
|
||||||
|
|
||||||
return attr;
|
return attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Attribute *AttributeSet::find(AttributeStandard std)
|
Attribute *AttributeSet::find(AttributeStandard std) const
|
||||||
{
|
{
|
||||||
foreach(Attribute& attr, attributes)
|
foreach(const Attribute& attr, attributes)
|
||||||
if(attr.std == std)
|
if(attr.std == std)
|
||||||
return &attr;
|
return (Attribute*)&attr;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -217,10 +292,14 @@ Attribute *AttributeSet::find(AttributeRequest& req)
|
|||||||
return find(req.std);
|
return find(req.std);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttributeSet::reserve(int numverts, int numtris)
|
void AttributeSet::reserve()
|
||||||
{
|
{
|
||||||
foreach(Attribute& attr, attributes)
|
foreach(Attribute& attr, attributes) {
|
||||||
attr.reserve(numverts, numtris);
|
if(triangle_mesh)
|
||||||
|
attr.reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), 0, 0);
|
||||||
|
if(curve_mesh)
|
||||||
|
attr.reserve(0, 0, curve_mesh->curves.size(), curve_mesh->curve_keys.size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttributeSet::clear()
|
void AttributeSet::clear()
|
||||||
@@ -235,9 +314,13 @@ AttributeRequest::AttributeRequest(ustring name_)
|
|||||||
name = name_;
|
name = name_;
|
||||||
std = ATTR_STD_NONE;
|
std = ATTR_STD_NONE;
|
||||||
|
|
||||||
type = TypeDesc::TypeFloat;
|
triangle_type = TypeDesc::TypeFloat;
|
||||||
element = ATTR_ELEMENT_NONE;
|
triangle_element = ATTR_ELEMENT_NONE;
|
||||||
offset = 0;
|
triangle_offset = 0;
|
||||||
|
|
||||||
|
curve_type = TypeDesc::TypeFloat;
|
||||||
|
curve_element = ATTR_ELEMENT_NONE;
|
||||||
|
curve_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
AttributeRequest::AttributeRequest(AttributeStandard std_)
|
AttributeRequest::AttributeRequest(AttributeStandard std_)
|
||||||
@@ -245,9 +328,13 @@ AttributeRequest::AttributeRequest(AttributeStandard std_)
|
|||||||
name = ustring();
|
name = ustring();
|
||||||
std = std_;
|
std = std_;
|
||||||
|
|
||||||
type = TypeDesc::TypeFloat;
|
triangle_type = TypeDesc::TypeFloat;
|
||||||
element = ATTR_ELEMENT_NONE;
|
triangle_element = ATTR_ELEMENT_NONE;
|
||||||
offset = 0;
|
triangle_offset = 0;
|
||||||
|
|
||||||
|
curve_type = TypeDesc::TypeFloat;
|
||||||
|
curve_element = ATTR_ELEMENT_NONE;
|
||||||
|
curve_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* AttributeRequestSet */
|
/* AttributeRequestSet */
|
||||||
|
@@ -21,7 +21,6 @@
|
|||||||
|
|
||||||
#include "kernel_types.h"
|
#include "kernel_types.h"
|
||||||
|
|
||||||
#include "util_attribute.h"
|
|
||||||
#include "util_list.h"
|
#include "util_list.h"
|
||||||
#include "util_param.h"
|
#include "util_param.h"
|
||||||
#include "util_types.h"
|
#include "util_types.h"
|
||||||
@@ -42,36 +41,34 @@ class Mesh;
|
|||||||
|
|
||||||
class Attribute {
|
class Attribute {
|
||||||
public:
|
public:
|
||||||
enum Element {
|
|
||||||
VERTEX,
|
|
||||||
FACE,
|
|
||||||
CORNER
|
|
||||||
};
|
|
||||||
|
|
||||||
ustring name;
|
ustring name;
|
||||||
AttributeStandard std;
|
AttributeStandard std;
|
||||||
|
|
||||||
TypeDesc type;
|
TypeDesc type;
|
||||||
vector<char> buffer;
|
vector<char> buffer;
|
||||||
Element element;
|
AttributeElement element;
|
||||||
|
|
||||||
Attribute() {}
|
Attribute() {}
|
||||||
void set(ustring name, TypeDesc type, Element element);
|
void set(ustring name, TypeDesc type, AttributeElement element);
|
||||||
void reserve(int numverts, int numfaces);
|
void reserve(int numverts, int numfaces, int numcurves, int numkeys);
|
||||||
|
|
||||||
size_t data_sizeof();
|
size_t data_sizeof() const;
|
||||||
size_t element_size(int numverts, int numfaces);
|
size_t element_size(int numverts, int numfaces, int numcurves, int numkeys) const;
|
||||||
size_t buffer_size(int numverts, int numfaces);
|
size_t buffer_size(int numverts, int numfaces, int numcurves, int numkeys) const;
|
||||||
|
|
||||||
char *data() { return (buffer.size())? &buffer[0]: NULL; };
|
char *data() { return (buffer.size())? &buffer[0]: NULL; };
|
||||||
float3 *data_float3() { return (float3*)data(); }
|
float3 *data_float3() { return (float3*)data(); }
|
||||||
float *data_float() { return (float*)data(); }
|
float *data_float() { return (float*)data(); }
|
||||||
|
|
||||||
const char *data() const { return (buffer.size())? &buffer[0]: NULL; }
|
const char *data() const { return (buffer.size())? &buffer[0]: NULL; }
|
||||||
const float3 *data_float3() const { return (float3*)data(); }
|
const float3 *data_float3() const { return (const float3*)data(); }
|
||||||
const float *data_float() const { return (float*)data(); }
|
const float *data_float() const { return (const float*)data(); }
|
||||||
|
|
||||||
|
void add(const float& f);
|
||||||
|
void add(const float3& f);
|
||||||
|
|
||||||
static bool same_storage(TypeDesc a, TypeDesc b);
|
static bool same_storage(TypeDesc a, TypeDesc b);
|
||||||
|
static const char *standard_name(AttributeStandard std);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Attribute Set
|
/* Attribute Set
|
||||||
@@ -80,23 +77,24 @@ public:
|
|||||||
|
|
||||||
class AttributeSet {
|
class AttributeSet {
|
||||||
public:
|
public:
|
||||||
Mesh *mesh;
|
Mesh *triangle_mesh;
|
||||||
|
Mesh *curve_mesh;
|
||||||
list<Attribute> attributes;
|
list<Attribute> attributes;
|
||||||
|
|
||||||
AttributeSet();
|
AttributeSet();
|
||||||
~AttributeSet();
|
~AttributeSet();
|
||||||
|
|
||||||
Attribute *add(ustring name, TypeDesc type, Attribute::Element element);
|
Attribute *add(ustring name, TypeDesc type, AttributeElement element);
|
||||||
Attribute *find(ustring name);
|
Attribute *find(ustring name) const;
|
||||||
void remove(ustring name);
|
void remove(ustring name);
|
||||||
|
|
||||||
Attribute *add(AttributeStandard std, ustring name = ustring());
|
Attribute *add(AttributeStandard std, ustring name = ustring());
|
||||||
Attribute *find(AttributeStandard std);
|
Attribute *find(AttributeStandard std) const;
|
||||||
void remove(AttributeStandard std);
|
void remove(AttributeStandard std);
|
||||||
|
|
||||||
Attribute *find(AttributeRequest& req);
|
Attribute *find(AttributeRequest& req);
|
||||||
|
|
||||||
void reserve(int numverts, int numfaces);
|
void reserve();
|
||||||
void clear();
|
void clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -104,7 +102,7 @@ public:
|
|||||||
*
|
*
|
||||||
* Request from a shader to use a certain attribute, so we can figure out
|
* Request from a shader to use a certain attribute, so we can figure out
|
||||||
* which ones we need to export from the host app end store for the kernel.
|
* which ones we need to export from the host app end store for the kernel.
|
||||||
* The attribute is found either by name or by standard. */
|
* The attribute is found either by name or by standard attribute type. */
|
||||||
|
|
||||||
class AttributeRequest {
|
class AttributeRequest {
|
||||||
public:
|
public:
|
||||||
@@ -112,9 +110,9 @@ public:
|
|||||||
AttributeStandard std;
|
AttributeStandard std;
|
||||||
|
|
||||||
/* temporary variables used by MeshManager */
|
/* temporary variables used by MeshManager */
|
||||||
TypeDesc type;
|
TypeDesc triangle_type, curve_type;
|
||||||
AttributeElement element;
|
AttributeElement triangle_element, curve_element;
|
||||||
int offset;
|
int triangle_offset, curve_offset;
|
||||||
|
|
||||||
AttributeRequest(ustring name_);
|
AttributeRequest(ustring name_);
|
||||||
AttributeRequest(AttributeStandard std);
|
AttributeRequest(AttributeStandard std);
|
||||||
|
160
intern/cycles/render/curves.cpp
Normal file
160
intern/cycles/render/curves.cpp
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Blender Foundation.
|
||||||
|
*
|
||||||
|
* 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 2
|
||||||
|
* 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, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "device.h"
|
||||||
|
#include "curves.h"
|
||||||
|
#include "mesh.h"
|
||||||
|
#include "object.h"
|
||||||
|
#include "scene.h"
|
||||||
|
|
||||||
|
#include "util_foreach.h"
|
||||||
|
#include "util_map.h"
|
||||||
|
#include "util_progress.h"
|
||||||
|
#include "util_vector.h"
|
||||||
|
|
||||||
|
CCL_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
/* Hair System Manager */
|
||||||
|
|
||||||
|
CurveSystemManager::CurveSystemManager()
|
||||||
|
{
|
||||||
|
primitive = CURVE_LINE_SEGMENTS;
|
||||||
|
line_method = CURVE_CORRECTED;
|
||||||
|
interpolation = CURVE_CARDINAL;
|
||||||
|
triangle_method = CURVE_CAMERA;
|
||||||
|
resolution = 3;
|
||||||
|
segments = 1;
|
||||||
|
|
||||||
|
normalmix = 1.0f;
|
||||||
|
encasing_ratio = 1.01f;
|
||||||
|
|
||||||
|
use_curves = true;
|
||||||
|
use_smooth = true;
|
||||||
|
use_cache = true;
|
||||||
|
use_parents = false;
|
||||||
|
use_encasing = true;
|
||||||
|
use_backfacing = false;
|
||||||
|
use_joined = false;
|
||||||
|
use_tangent_normal = false;
|
||||||
|
use_tangent_normal_geometry = false;
|
||||||
|
use_tangent_normal_correction = false;
|
||||||
|
|
||||||
|
need_update = true;
|
||||||
|
need_mesh_update = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurveSystemManager::~CurveSystemManager()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveSystemManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
|
||||||
|
{
|
||||||
|
if(!need_update)
|
||||||
|
return;
|
||||||
|
|
||||||
|
device_free(device, dscene);
|
||||||
|
|
||||||
|
progress.set_status("Updating Hair settings", "Copying Hair settings to device");
|
||||||
|
|
||||||
|
KernelCurves *kcurve= &dscene->data.curve_kernel_data;
|
||||||
|
|
||||||
|
kcurve->curveflags = 0;
|
||||||
|
|
||||||
|
if(primitive == CURVE_SEGMENTS)
|
||||||
|
kcurve->curveflags |= CURVE_KN_INTERPOLATE;
|
||||||
|
|
||||||
|
if(line_method == CURVE_ACCURATE)
|
||||||
|
kcurve->curveflags |= CURVE_KN_ACCURATE;
|
||||||
|
if(line_method == CURVE_CORRECTED)
|
||||||
|
kcurve->curveflags |= CURVE_KN_INTERSECTCORRECTION;
|
||||||
|
if(line_method == CURVE_POSTCORRECTED)
|
||||||
|
kcurve->curveflags |= CURVE_KN_POSTINTERSECTCORRECTION;
|
||||||
|
|
||||||
|
if(use_tangent_normal)
|
||||||
|
kcurve->curveflags |= CURVE_KN_TANGENTGNORMAL;
|
||||||
|
if(use_tangent_normal_correction)
|
||||||
|
kcurve->curveflags |= CURVE_KN_NORMALCORRECTION;
|
||||||
|
if(use_tangent_normal_geometry)
|
||||||
|
kcurve->curveflags |= CURVE_KN_TRUETANGENTGNORMAL;
|
||||||
|
if(use_joined)
|
||||||
|
kcurve->curveflags |= CURVE_KN_CURVEDATA;
|
||||||
|
if(use_backfacing)
|
||||||
|
kcurve->curveflags |= CURVE_KN_BACKFACING;
|
||||||
|
if(use_encasing)
|
||||||
|
kcurve->curveflags |= CURVE_KN_ENCLOSEFILTER;
|
||||||
|
|
||||||
|
kcurve->normalmix = normalmix;
|
||||||
|
kcurve->encasing_ratio = encasing_ratio;
|
||||||
|
|
||||||
|
if(progress.get_cancel()) return;
|
||||||
|
|
||||||
|
need_update = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveSystemManager::device_free(Device *device, DeviceScene *dscene)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CurveSystemManager::modified(const CurveSystemManager& CurveSystemManager)
|
||||||
|
{
|
||||||
|
return !(line_method == CurveSystemManager.line_method &&
|
||||||
|
interpolation == CurveSystemManager.interpolation &&
|
||||||
|
primitive == CurveSystemManager.primitive &&
|
||||||
|
use_encasing == CurveSystemManager.use_encasing &&
|
||||||
|
use_tangent_normal == CurveSystemManager.use_tangent_normal &&
|
||||||
|
use_tangent_normal_correction == CurveSystemManager.use_tangent_normal_correction &&
|
||||||
|
use_tangent_normal_geometry == CurveSystemManager.use_tangent_normal_geometry &&
|
||||||
|
encasing_ratio == CurveSystemManager.encasing_ratio &&
|
||||||
|
use_backfacing == CurveSystemManager.use_backfacing &&
|
||||||
|
normalmix == CurveSystemManager.normalmix &&
|
||||||
|
use_cache == CurveSystemManager.use_cache &&
|
||||||
|
use_smooth == CurveSystemManager.use_smooth &&
|
||||||
|
triangle_method == CurveSystemManager.triangle_method &&
|
||||||
|
resolution == CurveSystemManager.resolution &&
|
||||||
|
use_curves == CurveSystemManager.use_curves &&
|
||||||
|
use_joined == CurveSystemManager.use_joined &&
|
||||||
|
segments == CurveSystemManager.segments &&
|
||||||
|
use_parents == CurveSystemManager.use_parents);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CurveSystemManager::modified_mesh(const CurveSystemManager& CurveSystemManager)
|
||||||
|
{
|
||||||
|
return !(primitive == CurveSystemManager.primitive &&
|
||||||
|
interpolation == CurveSystemManager.interpolation &&
|
||||||
|
use_parents == CurveSystemManager.use_parents &&
|
||||||
|
use_smooth == CurveSystemManager.use_smooth &&
|
||||||
|
triangle_method == CurveSystemManager.triangle_method &&
|
||||||
|
resolution == CurveSystemManager.resolution &&
|
||||||
|
use_curves == CurveSystemManager.use_curves &&
|
||||||
|
use_joined == CurveSystemManager.use_joined &&
|
||||||
|
segments == CurveSystemManager.segments &&
|
||||||
|
use_cache == CurveSystemManager.use_cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveSystemManager::tag_update(Scene *scene)
|
||||||
|
{
|
||||||
|
need_update = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveSystemManager::tag_update_mesh()
|
||||||
|
{
|
||||||
|
need_mesh_update = true;
|
||||||
|
}
|
||||||
|
CCL_NAMESPACE_END
|
||||||
|
|
134
intern/cycles/render/curves.h
Normal file
134
intern/cycles/render/curves.h
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Blender Foundation.
|
||||||
|
*
|
||||||
|
* 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 2
|
||||||
|
* 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, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CURVES_H__
|
||||||
|
#define __CURVES_H__
|
||||||
|
|
||||||
|
#include "util_types.h"
|
||||||
|
#include "util_vector.h"
|
||||||
|
|
||||||
|
CCL_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class Device;
|
||||||
|
class DeviceScene;
|
||||||
|
class Progress;
|
||||||
|
class Scene;
|
||||||
|
|
||||||
|
typedef enum curve_presets {
|
||||||
|
CURVE_CUSTOM,
|
||||||
|
CURVE_TANGENT_SHADING,
|
||||||
|
CURVE_TRUE_NORMAL,
|
||||||
|
CURVE_ACCURATE_PRESET
|
||||||
|
} curve_presets;
|
||||||
|
|
||||||
|
typedef enum curve_primitives {
|
||||||
|
CURVE_TRIANGLES,
|
||||||
|
CURVE_LINE_SEGMENTS,
|
||||||
|
CURVE_SEGMENTS
|
||||||
|
} curve_primitives;
|
||||||
|
|
||||||
|
typedef enum curve_triangles {
|
||||||
|
CURVE_CAMERA,
|
||||||
|
CURVE_RIBBONS,
|
||||||
|
CURVE_TESSELATED
|
||||||
|
} curve_triangles;
|
||||||
|
|
||||||
|
typedef enum curve_lines {
|
||||||
|
CURVE_ACCURATE,
|
||||||
|
CURVE_CORRECTED,
|
||||||
|
CURVE_POSTCORRECTED,
|
||||||
|
CURVE_UNCORRECTED
|
||||||
|
} curve_lines;
|
||||||
|
|
||||||
|
typedef enum curve_interpolation {
|
||||||
|
CURVE_LINEAR,
|
||||||
|
CURVE_CARDINAL,
|
||||||
|
CURVE_BSPLINE
|
||||||
|
} curve_interpolation;
|
||||||
|
|
||||||
|
class ParticleCurveData {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ParticleCurveData();
|
||||||
|
~ParticleCurveData();
|
||||||
|
|
||||||
|
vector<int> psys_firstcurve;
|
||||||
|
vector<int> psys_curvenum;
|
||||||
|
vector<int> psys_shader;
|
||||||
|
|
||||||
|
vector<float> psys_rootradius;
|
||||||
|
vector<float> psys_tipradius;
|
||||||
|
vector<float> psys_shape;
|
||||||
|
vector<bool> psys_closetip;
|
||||||
|
|
||||||
|
vector<int> curve_firstkey;
|
||||||
|
vector<int> curve_keynum;
|
||||||
|
vector<float> curve_length;
|
||||||
|
vector<float3> curve_uv;
|
||||||
|
vector<float3> curve_vcol;
|
||||||
|
|
||||||
|
vector<float3> curvekey_co;
|
||||||
|
vector<float> curvekey_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* HairSystem Manager */
|
||||||
|
|
||||||
|
class CurveSystemManager {
|
||||||
|
public:
|
||||||
|
|
||||||
|
int primitive;
|
||||||
|
int line_method;
|
||||||
|
int interpolation;
|
||||||
|
int triangle_method;
|
||||||
|
int resolution;
|
||||||
|
int segments;
|
||||||
|
|
||||||
|
float normalmix;
|
||||||
|
float encasing_ratio;
|
||||||
|
|
||||||
|
bool use_curves;
|
||||||
|
bool use_smooth;
|
||||||
|
bool use_cache;
|
||||||
|
bool use_parents;
|
||||||
|
bool use_encasing;
|
||||||
|
bool use_backfacing;
|
||||||
|
bool use_tangent_normal;
|
||||||
|
bool use_tangent_normal_correction;
|
||||||
|
bool use_tangent_normal_geometry;
|
||||||
|
bool use_joined;
|
||||||
|
|
||||||
|
bool need_update;
|
||||||
|
bool need_mesh_update;
|
||||||
|
|
||||||
|
CurveSystemManager();
|
||||||
|
~CurveSystemManager();
|
||||||
|
|
||||||
|
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
|
||||||
|
void device_free(Device *device, DeviceScene *dscene);
|
||||||
|
bool modified(const CurveSystemManager& CurveSystemManager);
|
||||||
|
bool modified_mesh(const CurveSystemManager& CurveSystemManager);
|
||||||
|
|
||||||
|
void tag_update(Scene *scene);
|
||||||
|
void tag_update_mesh();
|
||||||
|
};
|
||||||
|
|
||||||
|
CCL_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif /* __CURVES_H__ */
|
||||||
|
|
@@ -142,6 +142,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
|
|||||||
/* count */
|
/* count */
|
||||||
size_t num_lights = scene->lights.size();
|
size_t num_lights = scene->lights.size();
|
||||||
size_t num_triangles = 0;
|
size_t num_triangles = 0;
|
||||||
|
size_t num_curve_segments = 0;
|
||||||
|
|
||||||
foreach(Object *object, scene->objects) {
|
foreach(Object *object, scene->objects) {
|
||||||
Mesh *mesh = object->mesh;
|
Mesh *mesh = object->mesh;
|
||||||
@@ -169,10 +170,19 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
|
|||||||
if(shader->sample_as_light && shader->has_surface_emission)
|
if(shader->sample_as_light && shader->has_surface_emission)
|
||||||
num_triangles++;
|
num_triangles++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* disabled for curves */
|
||||||
|
#if 0
|
||||||
|
foreach(Mesh::Curve& curve, mesh->curves) {
|
||||||
|
Shader *shader = scene->shaders[curve.shader];
|
||||||
|
|
||||||
|
if(shader->sample_as_light && shader->has_surface_emission)
|
||||||
|
num_curve_segments += curve.num_segments();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t num_distribution = num_triangles;
|
size_t num_distribution = num_triangles + num_curve_segments;
|
||||||
num_distribution += num_lights;
|
num_distribution += num_lights;
|
||||||
|
|
||||||
/* emission area */
|
/* emission area */
|
||||||
@@ -216,7 +226,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
|
|||||||
if(shader->sample_as_light && shader->has_surface_emission) {
|
if(shader->sample_as_light && shader->has_surface_emission) {
|
||||||
distribution[offset].x = totarea;
|
distribution[offset].x = totarea;
|
||||||
distribution[offset].y = __int_as_float(i + mesh->tri_offset);
|
distribution[offset].y = __int_as_float(i + mesh->tri_offset);
|
||||||
distribution[offset].z = 1.0f;
|
distribution[offset].z = __int_as_float(~0);
|
||||||
distribution[offset].w = __int_as_float(object_id);
|
distribution[offset].w = __int_as_float(object_id);
|
||||||
offset++;
|
offset++;
|
||||||
|
|
||||||
@@ -234,6 +244,40 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
|
|||||||
totarea += triangle_area(p1, p2, p3);
|
totarea += triangle_area(p1, p2, p3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*sample as light disabled for strands*/
|
||||||
|
#if 0
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
foreach(Mesh::Curve& curve, mesh->curves) {
|
||||||
|
Shader *shader = scene->shaders[curve.shader];
|
||||||
|
int first_key = curve.first_key;
|
||||||
|
|
||||||
|
if(shader->sample_as_light && shader->has_surface_emission) {
|
||||||
|
for(int j = 0; j < curve.num_segments(); j++) {
|
||||||
|
distribution[offset].x = totarea;
|
||||||
|
distribution[offset].y = __int_as_float(i + mesh->curve_offset); // XXX fix kernel code
|
||||||
|
distribution[offset].z = __int_as_float(j);
|
||||||
|
distribution[offset].w = __int_as_float(object_id);
|
||||||
|
offset++;
|
||||||
|
|
||||||
|
float3 p1 = mesh->curve_keys[first_key + j].loc;
|
||||||
|
float r1 = mesh->curve_keys[first_key + j].radius;
|
||||||
|
float3 p2 = mesh->curve_keys[first_key + j + 1].loc;
|
||||||
|
float r2 = mesh->curve_keys[first_key + j + 1].radius;
|
||||||
|
|
||||||
|
if(!transform_applied) {
|
||||||
|
p1 = transform_point(&tfm, p1);
|
||||||
|
p2 = transform_point(&tfm, p2);
|
||||||
|
}
|
||||||
|
|
||||||
|
totarea += M_PI_F * (r1 + r2) * len(p1 - p2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if(progress.get_cancel()) return;
|
if(progress.get_cancel()) return;
|
||||||
|
@@ -51,7 +51,11 @@ Mesh::Mesh()
|
|||||||
tri_offset = 0;
|
tri_offset = 0;
|
||||||
vert_offset = 0;
|
vert_offset = 0;
|
||||||
|
|
||||||
attributes.mesh = this;
|
curve_offset = 0;
|
||||||
|
curvekey_offset = 0;
|
||||||
|
|
||||||
|
attributes.triangle_mesh = this;
|
||||||
|
curve_attributes.curve_mesh = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mesh::~Mesh()
|
Mesh::~Mesh()
|
||||||
@@ -59,14 +63,18 @@ Mesh::~Mesh()
|
|||||||
delete bvh;
|
delete bvh;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mesh::reserve(int numverts, int numtris)
|
void Mesh::reserve(int numverts, int numtris, int numcurves, int numcurvekeys)
|
||||||
{
|
{
|
||||||
/* reserve space to add verts and triangles later */
|
/* reserve space to add verts and triangles later */
|
||||||
verts.resize(numverts);
|
verts.resize(numverts);
|
||||||
triangles.resize(numtris);
|
triangles.resize(numtris);
|
||||||
shader.resize(numtris);
|
shader.resize(numtris);
|
||||||
smooth.resize(numtris);
|
smooth.resize(numtris);
|
||||||
attributes.reserve(numverts, numtris);
|
curve_keys.resize(numcurvekeys);
|
||||||
|
curves.resize(numcurves);
|
||||||
|
|
||||||
|
attributes.reserve();
|
||||||
|
curve_attributes.reserve();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mesh::clear()
|
void Mesh::clear()
|
||||||
@@ -77,7 +85,11 @@ void Mesh::clear()
|
|||||||
shader.clear();
|
shader.clear();
|
||||||
smooth.clear();
|
smooth.clear();
|
||||||
|
|
||||||
|
curve_keys.clear();
|
||||||
|
curves.clear();
|
||||||
|
|
||||||
attributes.clear();
|
attributes.clear();
|
||||||
|
curve_attributes.clear();
|
||||||
used_shaders.clear();
|
used_shaders.clear();
|
||||||
|
|
||||||
transform_applied = false;
|
transform_applied = false;
|
||||||
@@ -86,24 +98,47 @@ void Mesh::clear()
|
|||||||
|
|
||||||
void Mesh::add_triangle(int v0, int v1, int v2, int shader_, bool smooth_)
|
void Mesh::add_triangle(int v0, int v1, int v2, int shader_, bool smooth_)
|
||||||
{
|
{
|
||||||
Triangle t;
|
Triangle tri;
|
||||||
t.v[0] = v0;
|
tri.v[0] = v0;
|
||||||
t.v[1] = v1;
|
tri.v[1] = v1;
|
||||||
t.v[2] = v2;
|
tri.v[2] = v2;
|
||||||
|
|
||||||
triangles.push_back(t);
|
triangles.push_back(tri);
|
||||||
shader.push_back(shader_);
|
shader.push_back(shader_);
|
||||||
smooth.push_back(smooth_);
|
smooth.push_back(smooth_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Mesh::add_curve_key(float3 co, float radius)
|
||||||
|
{
|
||||||
|
CurveKey key;
|
||||||
|
key.co = co;
|
||||||
|
key.radius = radius;
|
||||||
|
|
||||||
|
curve_keys.push_back(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mesh::add_curve(int first_key, int num_keys, int shader)
|
||||||
|
{
|
||||||
|
Curve curve;
|
||||||
|
curve.first_key = first_key;
|
||||||
|
curve.num_keys = num_keys;
|
||||||
|
curve.shader = shader;
|
||||||
|
|
||||||
|
curves.push_back(curve);
|
||||||
|
}
|
||||||
|
|
||||||
void Mesh::compute_bounds()
|
void Mesh::compute_bounds()
|
||||||
{
|
{
|
||||||
BoundBox bnds = BoundBox::empty;
|
BoundBox bnds = BoundBox::empty;
|
||||||
size_t verts_size = verts.size();
|
size_t verts_size = verts.size();
|
||||||
|
size_t curve_keys_size = curve_keys.size();
|
||||||
|
|
||||||
for(size_t i = 0; i < verts_size; i++)
|
for(size_t i = 0; i < verts_size; i++)
|
||||||
bnds.grow(verts[i]);
|
bnds.grow(verts[i]);
|
||||||
|
|
||||||
|
for(size_t i = 0; i < curve_keys_size; i++)
|
||||||
|
bnds.grow(curve_keys[i].co, curve_keys[i].radius);
|
||||||
|
|
||||||
/* happens mostly on empty meshes */
|
/* happens mostly on empty meshes */
|
||||||
if(!bnds.valid())
|
if(!bnds.valid())
|
||||||
bnds.grow(make_float3(0.0f, 0.0f, 0.0f));
|
bnds.grow(make_float3(0.0f, 0.0f, 0.0f));
|
||||||
@@ -135,7 +170,12 @@ void Mesh::add_face_normals()
|
|||||||
float3 v1 = verts_ptr[t.v[1]];
|
float3 v1 = verts_ptr[t.v[1]];
|
||||||
float3 v2 = verts_ptr[t.v[2]];
|
float3 v2 = verts_ptr[t.v[2]];
|
||||||
|
|
||||||
fN[i] = normalize(cross(v1 - v0, v2 - v0));
|
float3 norm = cross(v1 - v0, v2 - v0);
|
||||||
|
float normlen = len(norm);
|
||||||
|
if(normlen == 0.0f)
|
||||||
|
fN[i] = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
else
|
||||||
|
fN[i] = norm / normlen;
|
||||||
|
|
||||||
if(flip)
|
if(flip)
|
||||||
fN[i] = -fN[i];
|
fN[i] = -fN[i];
|
||||||
@@ -243,6 +283,43 @@ void Mesh::pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Mesh::pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset)
|
||||||
|
{
|
||||||
|
size_t curve_keys_size = curve_keys.size();
|
||||||
|
CurveKey *keys_ptr = NULL;
|
||||||
|
|
||||||
|
/* pack curve keys */
|
||||||
|
if(curve_keys_size) {
|
||||||
|
keys_ptr = &curve_keys[0];
|
||||||
|
|
||||||
|
for(size_t i = 0; i < curve_keys_size; i++) {
|
||||||
|
float3 p = keys_ptr[i].co;
|
||||||
|
float radius = keys_ptr[i].radius;
|
||||||
|
|
||||||
|
curve_key_co[i] = make_float4(p.x, p.y, p.z, radius);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pack curve segments */
|
||||||
|
size_t curve_num = curves.size();
|
||||||
|
|
||||||
|
if(curve_num) {
|
||||||
|
Curve *curve_ptr = &curves[0];
|
||||||
|
int shader_id = 0;
|
||||||
|
|
||||||
|
for(size_t i = 0; i < curve_num; i++) {
|
||||||
|
Curve curve = curve_ptr[i];
|
||||||
|
shader_id = scene->shader_manager->get_shader_id(curve.shader, this, false);
|
||||||
|
|
||||||
|
curve_data[i] = make_float4(
|
||||||
|
__int_as_float(curve.first_key + curvekey_offset),
|
||||||
|
__int_as_float(curve.num_keys),
|
||||||
|
__int_as_float(shader_id),
|
||||||
|
0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Mesh::compute_bvh(SceneParams *params, Progress *progress, int n, int total)
|
void Mesh::compute_bvh(SceneParams *params, Progress *progress, int n, int total)
|
||||||
{
|
{
|
||||||
if(progress->get_cancel())
|
if(progress->get_cancel())
|
||||||
@@ -327,7 +404,7 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att
|
|||||||
og->attribute_map.clear();
|
og->attribute_map.clear();
|
||||||
og->object_names.clear();
|
og->object_names.clear();
|
||||||
|
|
||||||
og->attribute_map.resize(scene->objects.size());
|
og->attribute_map.resize(scene->objects.size()*ATTR_PRIM_TYPES);
|
||||||
|
|
||||||
for(size_t i = 0; i < scene->objects.size(); i++) {
|
for(size_t i = 0; i < scene->objects.size(); i++) {
|
||||||
/* set object name to object index map */
|
/* set object name to object index map */
|
||||||
@@ -343,7 +420,8 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att
|
|||||||
osl_attr.elem = ATTR_ELEMENT_VALUE;
|
osl_attr.elem = ATTR_ELEMENT_VALUE;
|
||||||
osl_attr.value = attr;
|
osl_attr.value = attr;
|
||||||
|
|
||||||
og->attribute_map[i][attr.name()] = osl_attr;
|
og->attribute_map[i*ATTR_PRIM_TYPES][attr.name()] = osl_attr;
|
||||||
|
og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][attr.name()] = osl_attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find mesh attributes */
|
/* find mesh attributes */
|
||||||
@@ -357,27 +435,46 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att
|
|||||||
|
|
||||||
/* set object attributes */
|
/* set object attributes */
|
||||||
foreach(AttributeRequest& req, attributes.requests) {
|
foreach(AttributeRequest& req, attributes.requests) {
|
||||||
if(req.element == ATTR_ELEMENT_NONE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
OSLGlobals::Attribute osl_attr;
|
OSLGlobals::Attribute osl_attr;
|
||||||
|
|
||||||
osl_attr.elem = req.element;
|
if(req.triangle_element != ATTR_ELEMENT_NONE) {
|
||||||
osl_attr.offset = req.offset;
|
osl_attr.elem = req.triangle_element;
|
||||||
|
osl_attr.offset = req.triangle_offset;
|
||||||
|
|
||||||
if(req.type == TypeDesc::TypeFloat)
|
if(req.triangle_type == TypeDesc::TypeFloat)
|
||||||
osl_attr.type = TypeDesc::TypeFloat;
|
osl_attr.type = TypeDesc::TypeFloat;
|
||||||
else
|
else
|
||||||
osl_attr.type = TypeDesc::TypeColor;
|
osl_attr.type = TypeDesc::TypeColor;
|
||||||
|
|
||||||
if(req.std != ATTR_STD_NONE) {
|
if(req.std != ATTR_STD_NONE) {
|
||||||
/* if standard attribute, add lookup by geom: name convention */
|
/* if standard attribute, add lookup by geom: name convention */
|
||||||
ustring stdname(string("geom:") + string(attribute_standard_name(req.std)));
|
ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
|
||||||
og->attribute_map[i][stdname] = osl_attr;
|
og->attribute_map[i*ATTR_PRIM_TYPES][stdname] = osl_attr;
|
||||||
|
}
|
||||||
|
else if(req.name != ustring()) {
|
||||||
|
/* add lookup by mesh attribute name */
|
||||||
|
og->attribute_map[i*ATTR_PRIM_TYPES][req.name] = osl_attr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(req.name != ustring()) {
|
|
||||||
/* add lookup by mesh attribute name */
|
if(req.curve_element != ATTR_ELEMENT_NONE) {
|
||||||
og->attribute_map[i][req.name] = osl_attr;
|
osl_attr.elem = req.curve_element;
|
||||||
|
osl_attr.offset = req.curve_offset;
|
||||||
|
|
||||||
|
if(req.curve_type == TypeDesc::TypeFloat)
|
||||||
|
osl_attr.type = TypeDesc::TypeFloat;
|
||||||
|
else
|
||||||
|
osl_attr.type = TypeDesc::TypeColor;
|
||||||
|
|
||||||
|
if(req.std != ATTR_STD_NONE) {
|
||||||
|
/* if standard attribute, add lookup by geom: name convention */
|
||||||
|
ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
|
||||||
|
og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][stdname] = osl_attr;
|
||||||
|
}
|
||||||
|
else if(req.name != ustring()) {
|
||||||
|
/* add lookup by mesh attribute name */
|
||||||
|
og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][req.name] = osl_attr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -393,7 +490,7 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
|
|||||||
int attr_map_stride = 0;
|
int attr_map_stride = 0;
|
||||||
|
|
||||||
for(size_t i = 0; i < scene->meshes.size(); i++)
|
for(size_t i = 0; i < scene->meshes.size(); i++)
|
||||||
attr_map_stride = max(attr_map_stride, mesh_attributes[i].size()+1);
|
attr_map_stride = max(attr_map_stride, (mesh_attributes[i].size() + 1)*ATTR_PRIM_TYPES);
|
||||||
|
|
||||||
if(attr_map_stride == 0)
|
if(attr_map_stride == 0)
|
||||||
return;
|
return;
|
||||||
@@ -404,12 +501,13 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
|
|||||||
|
|
||||||
for(size_t i = 0; i < scene->objects.size(); i++) {
|
for(size_t i = 0; i < scene->objects.size(); i++) {
|
||||||
Object *object = scene->objects[i];
|
Object *object = scene->objects[i];
|
||||||
|
Mesh *mesh = object->mesh;
|
||||||
|
|
||||||
/* find mesh attributes */
|
/* find mesh attributes */
|
||||||
size_t j;
|
size_t j;
|
||||||
|
|
||||||
for(j = 0; j < scene->meshes.size(); j++)
|
for(j = 0; j < scene->meshes.size(); j++)
|
||||||
if(scene->meshes[j] == object->mesh)
|
if(scene->meshes[j] == mesh)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
AttributeRequestSet& attributes = mesh_attributes[j];
|
AttributeRequestSet& attributes = mesh_attributes[j];
|
||||||
@@ -425,14 +523,29 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
|
|||||||
else
|
else
|
||||||
id = scene->shader_manager->get_attribute_id(req.std);
|
id = scene->shader_manager->get_attribute_id(req.std);
|
||||||
|
|
||||||
attr_map[index].x = id;
|
if(mesh->triangles.size()) {
|
||||||
attr_map[index].y = req.element;
|
attr_map[index].x = id;
|
||||||
attr_map[index].z = as_uint(req.offset);
|
attr_map[index].y = req.triangle_element;
|
||||||
|
attr_map[index].z = as_uint(req.triangle_offset);
|
||||||
|
|
||||||
if(req.type == TypeDesc::TypeFloat)
|
if(req.triangle_type == TypeDesc::TypeFloat)
|
||||||
attr_map[index].w = NODE_ATTR_FLOAT;
|
attr_map[index].w = NODE_ATTR_FLOAT;
|
||||||
else
|
else
|
||||||
attr_map[index].w = NODE_ATTR_FLOAT3;
|
attr_map[index].w = NODE_ATTR_FLOAT3;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if(mesh->curves.size()) {
|
||||||
|
attr_map[index].x = id;
|
||||||
|
attr_map[index].y = req.curve_element;
|
||||||
|
attr_map[index].z = as_uint(req.curve_offset);
|
||||||
|
|
||||||
|
if(req.curve_type == TypeDesc::TypeFloat)
|
||||||
|
attr_map[index].w = NODE_ATTR_FLOAT;
|
||||||
|
else
|
||||||
|
attr_map[index].w = NODE_ATTR_FLOAT3;
|
||||||
|
}
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
@@ -442,6 +555,15 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
|
|||||||
attr_map[index].y = 0;
|
attr_map[index].y = 0;
|
||||||
attr_map[index].z = 0;
|
attr_map[index].z = 0;
|
||||||
attr_map[index].w = 0;
|
attr_map[index].w = 0;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
attr_map[index].x = ATTR_STD_NONE;
|
||||||
|
attr_map[index].y = 0;
|
||||||
|
attr_map[index].z = 0;
|
||||||
|
attr_map[index].w = 0;
|
||||||
|
|
||||||
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy to device */
|
/* copy to device */
|
||||||
@@ -449,6 +571,60 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
|
|||||||
device->tex_alloc("__attributes_map", dscene->attributes_map);
|
device->tex_alloc("__attributes_map", dscene->attributes_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void update_attribute_element_offset(Mesh *mesh, vector<float>& attr_float, vector<float4>& attr_float3,
|
||||||
|
Attribute *mattr, TypeDesc& type, int& offset, AttributeElement& element)
|
||||||
|
{
|
||||||
|
if(mattr) {
|
||||||
|
/* store element and type */
|
||||||
|
element = mattr->element;
|
||||||
|
type = mattr->type;
|
||||||
|
|
||||||
|
/* store attribute data in arrays */
|
||||||
|
size_t size = mattr->element_size(
|
||||||
|
mesh->verts.size(),
|
||||||
|
mesh->triangles.size(),
|
||||||
|
mesh->curves.size(),
|
||||||
|
mesh->curve_keys.size());
|
||||||
|
|
||||||
|
if(mattr->type == TypeDesc::TypeFloat) {
|
||||||
|
float *data = mattr->data_float();
|
||||||
|
offset = attr_float.size();
|
||||||
|
|
||||||
|
attr_float.resize(attr_float.size() + size);
|
||||||
|
|
||||||
|
for(size_t k = 0; k < size; k++)
|
||||||
|
attr_float[offset+k] = data[k];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
float3 *data = mattr->data_float3();
|
||||||
|
offset = attr_float3.size();
|
||||||
|
|
||||||
|
attr_float3.resize(attr_float3.size() + size);
|
||||||
|
|
||||||
|
for(size_t k = 0; k < size; k++)
|
||||||
|
attr_float3[offset+k] = float3_to_float4(data[k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mesh vertex/curve index is global, not per object, so we sneak
|
||||||
|
* a correction for that in here */
|
||||||
|
if(element == ATTR_ELEMENT_VERTEX)
|
||||||
|
offset -= mesh->vert_offset;
|
||||||
|
else if(element == ATTR_ELEMENT_FACE)
|
||||||
|
offset -= mesh->tri_offset;
|
||||||
|
else if(element == ATTR_ELEMENT_CORNER)
|
||||||
|
offset -= 3*mesh->tri_offset;
|
||||||
|
else if(element == ATTR_ELEMENT_CURVE)
|
||||||
|
offset -= mesh->curve_offset;
|
||||||
|
else if(element == ATTR_ELEMENT_CURVE_KEY)
|
||||||
|
offset -= mesh->curvekey_offset;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* attribute not found */
|
||||||
|
element = ATTR_ELEMENT_NONE;
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
|
void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
|
||||||
{
|
{
|
||||||
progress.set_status("Updating Mesh", "Computing attributes");
|
progress.set_status("Updating Mesh", "Computing attributes");
|
||||||
@@ -482,66 +658,24 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
|
|||||||
/* todo: we now store std and name attributes from requests even if
|
/* todo: we now store std and name attributes from requests even if
|
||||||
* they actually refer to the same mesh attributes, optimize */
|
* they actually refer to the same mesh attributes, optimize */
|
||||||
foreach(AttributeRequest& req, attributes.requests) {
|
foreach(AttributeRequest& req, attributes.requests) {
|
||||||
Attribute *mattr = mesh->attributes.find(req);
|
Attribute *triangle_mattr = mesh->attributes.find(req);
|
||||||
|
Attribute *curve_mattr = mesh->curve_attributes.find(req);
|
||||||
|
|
||||||
/* todo: get rid of this exception */
|
/* todo: get rid of this exception, it's only here for giving some
|
||||||
if(!mattr && req.std == ATTR_STD_GENERATED) {
|
* working texture coordinate for subdivision as we can't preserve
|
||||||
mattr = mesh->attributes.add(ATTR_STD_GENERATED);
|
* any attributes yet */
|
||||||
|
if(!triangle_mattr && req.std == ATTR_STD_GENERATED) {
|
||||||
|
triangle_mattr = mesh->attributes.add(ATTR_STD_GENERATED);
|
||||||
if(mesh->verts.size())
|
if(mesh->verts.size())
|
||||||
memcpy(mattr->data_float3(), &mesh->verts[0], sizeof(float3)*mesh->verts.size());
|
memcpy(triangle_mattr->data_float3(), &mesh->verts[0], sizeof(float3)*mesh->verts.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* attribute not found */
|
update_attribute_element_offset(mesh, attr_float, attr_float3, triangle_mattr,
|
||||||
if(!mattr) {
|
req.triangle_type, req.triangle_offset, req.triangle_element);
|
||||||
req.element = ATTR_ELEMENT_NONE;
|
|
||||||
req.offset = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we abuse AttributeRequest to pass on info like element and
|
|
||||||
* offset, it doesn't really make sense but is convenient */
|
|
||||||
|
|
||||||
/* store element and type */
|
|
||||||
if(mattr->element == Attribute::VERTEX)
|
|
||||||
req.element = ATTR_ELEMENT_VERTEX;
|
|
||||||
else if(mattr->element == Attribute::FACE)
|
|
||||||
req.element = ATTR_ELEMENT_FACE;
|
|
||||||
else if(mattr->element == Attribute::CORNER)
|
|
||||||
req.element = ATTR_ELEMENT_CORNER;
|
|
||||||
|
|
||||||
req.type = mattr->type;
|
|
||||||
|
|
||||||
/* store attribute data in arrays */
|
|
||||||
size_t size = mattr->element_size(mesh->verts.size(), mesh->triangles.size());
|
|
||||||
|
|
||||||
if(mattr->type == TypeDesc::TypeFloat) {
|
|
||||||
float *data = mattr->data_float();
|
|
||||||
req.offset = attr_float.size();
|
|
||||||
|
|
||||||
attr_float.resize(attr_float.size() + size);
|
|
||||||
|
|
||||||
for(size_t k = 0; k < size; k++)
|
|
||||||
attr_float[req.offset+k] = data[k];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
float3 *data = mattr->data_float3();
|
|
||||||
req.offset = attr_float3.size();
|
|
||||||
|
|
||||||
attr_float3.resize(attr_float3.size() + size);
|
|
||||||
|
|
||||||
for(size_t k = 0; k < size; k++)
|
|
||||||
attr_float3[req.offset+k] = float3_to_float4(data[k]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* mesh vertex/triangle index is global, not per object, so we sneak
|
|
||||||
* a correction for that in here */
|
|
||||||
if(req.element == ATTR_ELEMENT_VERTEX)
|
|
||||||
req.offset -= mesh->vert_offset;
|
|
||||||
else if(mattr->element == Attribute::FACE)
|
|
||||||
req.offset -= mesh->tri_offset;
|
|
||||||
else if(mattr->element == Attribute::CORNER)
|
|
||||||
req.offset -= 3*mesh->tri_offset;
|
|
||||||
|
|
||||||
|
update_attribute_element_offset(mesh, attr_float, attr_float3, curve_mattr,
|
||||||
|
req.curve_type, req.curve_offset, req.curve_element);
|
||||||
|
|
||||||
if(progress.get_cancel()) return;
|
if(progress.get_cancel()) return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -573,39 +707,62 @@ void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene
|
|||||||
size_t vert_size = 0;
|
size_t vert_size = 0;
|
||||||
size_t tri_size = 0;
|
size_t tri_size = 0;
|
||||||
|
|
||||||
|
size_t curve_key_size = 0;
|
||||||
|
size_t curve_size = 0;
|
||||||
|
|
||||||
foreach(Mesh *mesh, scene->meshes) {
|
foreach(Mesh *mesh, scene->meshes) {
|
||||||
mesh->vert_offset = vert_size;
|
mesh->vert_offset = vert_size;
|
||||||
mesh->tri_offset = tri_size;
|
mesh->tri_offset = tri_size;
|
||||||
|
|
||||||
|
mesh->curvekey_offset = curve_key_size;
|
||||||
|
mesh->curve_offset = curve_size;
|
||||||
|
|
||||||
vert_size += mesh->verts.size();
|
vert_size += mesh->verts.size();
|
||||||
tri_size += mesh->triangles.size();
|
tri_size += mesh->triangles.size();
|
||||||
|
|
||||||
|
curve_key_size += mesh->curve_keys.size();
|
||||||
|
curve_size += mesh->curves.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tri_size == 0)
|
if(tri_size != 0) {
|
||||||
return;
|
/* normals */
|
||||||
|
progress.set_status("Updating Mesh", "Computing normals");
|
||||||
|
|
||||||
/* normals */
|
float4 *normal = dscene->tri_normal.resize(tri_size);
|
||||||
progress.set_status("Updating Mesh", "Computing normals");
|
float4 *vnormal = dscene->tri_vnormal.resize(vert_size);
|
||||||
|
float4 *tri_verts = dscene->tri_verts.resize(vert_size);
|
||||||
|
float4 *tri_vindex = dscene->tri_vindex.resize(tri_size);
|
||||||
|
|
||||||
float4 *normal = dscene->tri_normal.resize(tri_size);
|
foreach(Mesh *mesh, scene->meshes) {
|
||||||
float4 *vnormal = dscene->tri_vnormal.resize(vert_size);
|
mesh->pack_normals(scene, &normal[mesh->tri_offset], &vnormal[mesh->vert_offset]);
|
||||||
float4 *tri_verts = dscene->tri_verts.resize(vert_size);
|
mesh->pack_verts(&tri_verts[mesh->vert_offset], &tri_vindex[mesh->tri_offset], mesh->vert_offset);
|
||||||
float4 *tri_vindex = dscene->tri_vindex.resize(tri_size);
|
|
||||||
|
|
||||||
foreach(Mesh *mesh, scene->meshes) {
|
if(progress.get_cancel()) return;
|
||||||
mesh->pack_normals(scene, &normal[mesh->tri_offset], &vnormal[mesh->vert_offset]);
|
}
|
||||||
mesh->pack_verts(&tri_verts[mesh->vert_offset], &tri_vindex[mesh->tri_offset], mesh->vert_offset);
|
|
||||||
|
|
||||||
if(progress.get_cancel()) return;
|
/* vertex coordinates */
|
||||||
|
progress.set_status("Updating Mesh", "Copying Mesh to device");
|
||||||
|
|
||||||
|
device->tex_alloc("__tri_normal", dscene->tri_normal);
|
||||||
|
device->tex_alloc("__tri_vnormal", dscene->tri_vnormal);
|
||||||
|
device->tex_alloc("__tri_verts", dscene->tri_verts);
|
||||||
|
device->tex_alloc("__tri_vindex", dscene->tri_vindex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vertex coordinates */
|
if(curve_size != 0) {
|
||||||
progress.set_status("Updating Mesh", "Copying Mesh to device");
|
progress.set_status("Updating Mesh", "Copying Strands to device");
|
||||||
|
|
||||||
device->tex_alloc("__tri_normal", dscene->tri_normal);
|
float4 *curve_keys = dscene->curve_keys.resize(curve_key_size);
|
||||||
device->tex_alloc("__tri_vnormal", dscene->tri_vnormal);
|
float4 *curves = dscene->curves.resize(curve_size);
|
||||||
device->tex_alloc("__tri_verts", dscene->tri_verts);
|
|
||||||
device->tex_alloc("__tri_vindex", dscene->tri_vindex);
|
foreach(Mesh *mesh, scene->meshes) {
|
||||||
|
mesh->pack_curves(scene, &curve_keys[mesh->curvekey_offset], &curves[mesh->curve_offset], mesh->curvekey_offset);
|
||||||
|
if(progress.get_cancel()) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
device->tex_alloc("__curve_keys", dscene->curve_keys);
|
||||||
|
device->tex_alloc("__curves", dscene->curves);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
|
void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
|
||||||
@@ -642,6 +799,10 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
|
|||||||
dscene->tri_woop.reference(&pack.tri_woop[0], pack.tri_woop.size());
|
dscene->tri_woop.reference(&pack.tri_woop[0], pack.tri_woop.size());
|
||||||
device->tex_alloc("__tri_woop", dscene->tri_woop);
|
device->tex_alloc("__tri_woop", dscene->tri_woop);
|
||||||
}
|
}
|
||||||
|
if(pack.prim_segment.size()) {
|
||||||
|
dscene->prim_segment.reference((uint*)&pack.prim_segment[0], pack.prim_segment.size());
|
||||||
|
device->tex_alloc("__prim_segment", dscene->prim_segment);
|
||||||
|
}
|
||||||
if(pack.prim_visibility.size()) {
|
if(pack.prim_visibility.size()) {
|
||||||
dscene->prim_visibility.reference((uint*)&pack.prim_visibility[0], pack.prim_visibility.size());
|
dscene->prim_visibility.reference((uint*)&pack.prim_visibility[0], pack.prim_visibility.size());
|
||||||
device->tex_alloc("__prim_visibility", dscene->prim_visibility);
|
device->tex_alloc("__prim_visibility", dscene->prim_visibility);
|
||||||
@@ -751,6 +912,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
|
|||||||
device->tex_free(dscene->bvh_nodes);
|
device->tex_free(dscene->bvh_nodes);
|
||||||
device->tex_free(dscene->object_node);
|
device->tex_free(dscene->object_node);
|
||||||
device->tex_free(dscene->tri_woop);
|
device->tex_free(dscene->tri_woop);
|
||||||
|
device->tex_free(dscene->prim_segment);
|
||||||
device->tex_free(dscene->prim_visibility);
|
device->tex_free(dscene->prim_visibility);
|
||||||
device->tex_free(dscene->prim_index);
|
device->tex_free(dscene->prim_index);
|
||||||
device->tex_free(dscene->prim_object);
|
device->tex_free(dscene->prim_object);
|
||||||
@@ -758,6 +920,8 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
|
|||||||
device->tex_free(dscene->tri_vnormal);
|
device->tex_free(dscene->tri_vnormal);
|
||||||
device->tex_free(dscene->tri_vindex);
|
device->tex_free(dscene->tri_vindex);
|
||||||
device->tex_free(dscene->tri_verts);
|
device->tex_free(dscene->tri_verts);
|
||||||
|
device->tex_free(dscene->curves);
|
||||||
|
device->tex_free(dscene->curve_keys);
|
||||||
device->tex_free(dscene->attributes_map);
|
device->tex_free(dscene->attributes_map);
|
||||||
device->tex_free(dscene->attributes_float);
|
device->tex_free(dscene->attributes_float);
|
||||||
device->tex_free(dscene->attributes_float3);
|
device->tex_free(dscene->attributes_float3);
|
||||||
@@ -765,6 +929,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
|
|||||||
dscene->bvh_nodes.clear();
|
dscene->bvh_nodes.clear();
|
||||||
dscene->object_node.clear();
|
dscene->object_node.clear();
|
||||||
dscene->tri_woop.clear();
|
dscene->tri_woop.clear();
|
||||||
|
dscene->prim_segment.clear();
|
||||||
dscene->prim_visibility.clear();
|
dscene->prim_visibility.clear();
|
||||||
dscene->prim_index.clear();
|
dscene->prim_index.clear();
|
||||||
dscene->prim_object.clear();
|
dscene->prim_object.clear();
|
||||||
@@ -772,6 +937,8 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
|
|||||||
dscene->tri_vnormal.clear();
|
dscene->tri_vnormal.clear();
|
||||||
dscene->tri_vindex.clear();
|
dscene->tri_vindex.clear();
|
||||||
dscene->tri_verts.clear();
|
dscene->tri_verts.clear();
|
||||||
|
dscene->curves.clear();
|
||||||
|
dscene->curve_keys.clear();
|
||||||
dscene->attributes_map.clear();
|
dscene->attributes_map.clear();
|
||||||
dscene->attributes_float.clear();
|
dscene->attributes_float.clear();
|
||||||
dscene->attributes_float3.clear();
|
dscene->attributes_float3.clear();
|
||||||
|
@@ -50,6 +50,21 @@ public:
|
|||||||
int v[3];
|
int v[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Mesh Curve */
|
||||||
|
struct Curve {
|
||||||
|
int first_key;
|
||||||
|
int num_keys;
|
||||||
|
uint shader;
|
||||||
|
uint pad;
|
||||||
|
|
||||||
|
int num_segments() { return num_keys - 1; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CurveKey {
|
||||||
|
float3 co;
|
||||||
|
float radius;
|
||||||
|
};
|
||||||
|
|
||||||
/* Displacement */
|
/* Displacement */
|
||||||
enum DisplacementMethod {
|
enum DisplacementMethod {
|
||||||
DISPLACE_BUMP,
|
DISPLACE_BUMP,
|
||||||
@@ -65,8 +80,12 @@ public:
|
|||||||
vector<uint> shader;
|
vector<uint> shader;
|
||||||
vector<bool> smooth;
|
vector<bool> smooth;
|
||||||
|
|
||||||
|
vector<CurveKey> curve_keys;
|
||||||
|
vector<Curve> curves;
|
||||||
|
|
||||||
vector<uint> used_shaders;
|
vector<uint> used_shaders;
|
||||||
AttributeSet attributes;
|
AttributeSet attributes;
|
||||||
|
AttributeSet curve_attributes;
|
||||||
|
|
||||||
BoundBox bounds;
|
BoundBox bounds;
|
||||||
bool transform_applied;
|
bool transform_applied;
|
||||||
@@ -82,13 +101,18 @@ public:
|
|||||||
size_t tri_offset;
|
size_t tri_offset;
|
||||||
size_t vert_offset;
|
size_t vert_offset;
|
||||||
|
|
||||||
|
size_t curve_offset;
|
||||||
|
size_t curvekey_offset;
|
||||||
|
|
||||||
/* Functions */
|
/* Functions */
|
||||||
Mesh();
|
Mesh();
|
||||||
~Mesh();
|
~Mesh();
|
||||||
|
|
||||||
void reserve(int numverts, int numfaces);
|
void reserve(int numverts, int numfaces, int numcurves, int numcurvekeys);
|
||||||
void clear();
|
void clear();
|
||||||
void add_triangle(int v0, int v1, int v2, int shader, bool smooth);
|
void add_triangle(int v0, int v1, int v2, int shader, bool smooth);
|
||||||
|
void add_curve_key(float3 loc, float radius);
|
||||||
|
void add_curve(int first_key, int num_keys, int shader);
|
||||||
|
|
||||||
void compute_bounds();
|
void compute_bounds();
|
||||||
void add_face_normals();
|
void add_face_normals();
|
||||||
@@ -96,6 +120,7 @@ public:
|
|||||||
|
|
||||||
void pack_normals(Scene *scene, float4 *normal, float4 *vnormal);
|
void pack_normals(Scene *scene, float4 *normal, float4 *vnormal);
|
||||||
void pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset);
|
void pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset);
|
||||||
|
void pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset);
|
||||||
void compute_bvh(SceneParams *params, Progress *progress, int n, int total);
|
void compute_bvh(SceneParams *params, Progress *progress, int n, int total);
|
||||||
|
|
||||||
bool need_attribute(Scene *scene, AttributeStandard std);
|
bool need_attribute(Scene *scene, AttributeStandard std);
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
|
#include "object.h"
|
||||||
#include "scene.h"
|
#include "scene.h"
|
||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
|
|
||||||
@@ -41,11 +42,24 @@ bool MeshManager::displace(Device *device, Scene *scene, Mesh *mesh, Progress& p
|
|||||||
if(!has_displacement)
|
if(!has_displacement)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
string msg = string_printf("Computing Displacement %s", mesh->name.c_str());
|
||||||
|
progress.set_status("Updating Mesh", msg);
|
||||||
|
|
||||||
|
/* find object index. todo: is arbitrary */
|
||||||
|
size_t object_index = ~0;
|
||||||
|
|
||||||
|
for(size_t i = 0; i < scene->objects.size(); i++) {
|
||||||
|
if(scene->objects[i]->mesh == mesh) {
|
||||||
|
object_index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* setup input for device task */
|
/* setup input for device task */
|
||||||
vector<bool> done(mesh->verts.size(), false);
|
vector<bool> done(mesh->verts.size(), false);
|
||||||
device_vector<uint4> d_input;
|
device_vector<uint4> d_input;
|
||||||
uint4 *d_input_data = d_input.resize(mesh->verts.size());
|
uint4 *d_input_data = d_input.resize(mesh->verts.size());
|
||||||
size_t d_input_offset = 0;
|
size_t d_input_size = 0;
|
||||||
|
|
||||||
for(size_t i = 0; i < mesh->triangles.size(); i++) {
|
for(size_t i = 0; i < mesh->triangles.size(); i++) {
|
||||||
Mesh::Triangle t = mesh->triangles[i];
|
Mesh::Triangle t = mesh->triangles[i];
|
||||||
@@ -61,8 +75,8 @@ bool MeshManager::displace(Device *device, Scene *scene, Mesh *mesh, Progress& p
|
|||||||
done[t.v[j]] = true;
|
done[t.v[j]] = true;
|
||||||
|
|
||||||
/* set up object, primitive and barycentric coordinates */
|
/* set up object, primitive and barycentric coordinates */
|
||||||
/* when used, non-instanced convention: object = -object-1; */
|
/* when used, non-instanced convention: object = ~object */
|
||||||
int object = ~0; /* todo */
|
int object = ~object_index;
|
||||||
int prim = mesh->tri_offset + i;
|
int prim = mesh->tri_offset + i;
|
||||||
float u, v;
|
float u, v;
|
||||||
|
|
||||||
@@ -81,16 +95,16 @@ bool MeshManager::displace(Device *device, Scene *scene, Mesh *mesh, Progress& p
|
|||||||
|
|
||||||
/* back */
|
/* back */
|
||||||
uint4 in = make_uint4(object, prim, __float_as_int(u), __float_as_int(v));
|
uint4 in = make_uint4(object, prim, __float_as_int(u), __float_as_int(v));
|
||||||
d_input_data[d_input_offset++] = in;
|
d_input_data[d_input_size++] = in;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(d_input_offset == 0)
|
if(d_input_size == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* run device task */
|
/* run device task */
|
||||||
device_vector<float4> d_output;
|
device_vector<float4> d_output;
|
||||||
d_output.resize(d_input.size());
|
d_output.resize(d_input_size);
|
||||||
|
|
||||||
device->mem_alloc(d_input, MEM_READ_ONLY);
|
device->mem_alloc(d_input, MEM_READ_ONLY);
|
||||||
device->mem_copy_to(d_input);
|
device->mem_copy_to(d_input);
|
||||||
@@ -101,7 +115,7 @@ bool MeshManager::displace(Device *device, Scene *scene, Mesh *mesh, Progress& p
|
|||||||
task.shader_output = d_output.device_pointer;
|
task.shader_output = d_output.device_pointer;
|
||||||
task.shader_eval_type = SHADER_EVAL_DISPLACE;
|
task.shader_eval_type = SHADER_EVAL_DISPLACE;
|
||||||
task.shader_x = 0;
|
task.shader_x = 0;
|
||||||
task.shader_w = d_input.size();
|
task.shader_w = d_output.size();
|
||||||
|
|
||||||
device->task_add(task);
|
device->task_add(task);
|
||||||
device->task_wait();
|
device->task_wait();
|
||||||
|
@@ -2240,6 +2240,63 @@ void ParticleInfoNode::compile(OSLCompiler& compiler)
|
|||||||
compiler.add(this, "node_particle_info");
|
compiler.add(this, "node_particle_info");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Hair Info */
|
||||||
|
|
||||||
|
HairInfoNode::HairInfoNode()
|
||||||
|
: ShaderNode("hair_info")
|
||||||
|
{
|
||||||
|
add_output("Is Strand", SHADER_SOCKET_FLOAT);
|
||||||
|
add_output("Intercept", SHADER_SOCKET_FLOAT);
|
||||||
|
add_output("Thickness", SHADER_SOCKET_FLOAT);
|
||||||
|
add_output("Tangent Normal", SHADER_SOCKET_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HairInfoNode::attributes(AttributeRequestSet *attributes)
|
||||||
|
{
|
||||||
|
ShaderOutput *intercept_out = output("Intercept");
|
||||||
|
|
||||||
|
if(!intercept_out->links.empty())
|
||||||
|
attributes->add(ATTR_STD_CURVE_INTERCEPT);
|
||||||
|
|
||||||
|
ShaderNode::attributes(attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HairInfoNode::compile(SVMCompiler& compiler)
|
||||||
|
{
|
||||||
|
ShaderOutput *out;
|
||||||
|
|
||||||
|
out = output("Is Strand");
|
||||||
|
if(!out->links.empty()) {
|
||||||
|
compiler.stack_assign(out);
|
||||||
|
compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_IS_STRAND, out->stack_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
out = output("Intercept");
|
||||||
|
if(!out->links.empty()) {
|
||||||
|
int attr = compiler.attribute(ATTR_STD_CURVE_INTERCEPT);
|
||||||
|
compiler.stack_assign(out);
|
||||||
|
compiler.add_node(NODE_ATTR, attr, out->stack_offset, NODE_ATTR_FLOAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
out = output("Thickness");
|
||||||
|
if(!out->links.empty()) {
|
||||||
|
compiler.stack_assign(out);
|
||||||
|
compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_THICKNESS, out->stack_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
out = output("Tangent Normal");
|
||||||
|
if(!out->links.empty()) {
|
||||||
|
compiler.stack_assign(out);
|
||||||
|
compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_TANGENT_NORMAL, out->stack_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void HairInfoNode::compile(OSLCompiler& compiler)
|
||||||
|
{
|
||||||
|
compiler.add(this, "node_hair_info");
|
||||||
|
}
|
||||||
|
|
||||||
/* Value */
|
/* Value */
|
||||||
|
|
||||||
ValueNode::ValueNode()
|
ValueNode::ValueNode()
|
||||||
|
@@ -331,6 +331,13 @@ public:
|
|||||||
void attributes(AttributeRequestSet *attributes);
|
void attributes(AttributeRequestSet *attributes);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class HairInfoNode : public ShaderNode {
|
||||||
|
public:
|
||||||
|
SHADER_NODE_CLASS(HairInfoNode)
|
||||||
|
|
||||||
|
void attributes(AttributeRequestSet *attributes);
|
||||||
|
};
|
||||||
|
|
||||||
class ValueNode : public ShaderNode {
|
class ValueNode : public ShaderNode {
|
||||||
public:
|
public:
|
||||||
SHADER_NODE_CLASS(ValueNode)
|
SHADER_NODE_CLASS(ValueNode)
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "light.h"
|
#include "light.h"
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
|
#include "curves.h"
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
#include "scene.h"
|
#include "scene.h"
|
||||||
|
|
||||||
@@ -45,6 +46,7 @@ Object::Object()
|
|||||||
motion.post = transform_identity();
|
motion.post = transform_identity();
|
||||||
use_motion = false;
|
use_motion = false;
|
||||||
use_holdout = false;
|
use_holdout = false;
|
||||||
|
curverender = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object::~Object()
|
Object::~Object()
|
||||||
@@ -86,6 +88,10 @@ void Object::apply_transform()
|
|||||||
for(size_t i = 0; i < mesh->verts.size(); i++)
|
for(size_t i = 0; i < mesh->verts.size(); i++)
|
||||||
mesh->verts[i] = transform_point(&tfm, mesh->verts[i]);
|
mesh->verts[i] = transform_point(&tfm, mesh->verts[i]);
|
||||||
|
|
||||||
|
for(size_t i = 0; i < mesh->curve_keys.size(); i++)
|
||||||
|
mesh->curve_keys[i].co = transform_point(&tfm, mesh->curve_keys[i].co);
|
||||||
|
|
||||||
|
Attribute *attr_tangent = mesh->curve_attributes.find(ATTR_STD_CURVE_TANGENT);
|
||||||
Attribute *attr_fN = mesh->attributes.find(ATTR_STD_FACE_NORMAL);
|
Attribute *attr_fN = mesh->attributes.find(ATTR_STD_FACE_NORMAL);
|
||||||
Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
|
Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
|
||||||
|
|
||||||
@@ -110,6 +116,13 @@ void Object::apply_transform()
|
|||||||
vN[i] = transform_direction(&ntfm, vN[i]);
|
vN[i] = transform_direction(&ntfm, vN[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(attr_tangent) {
|
||||||
|
float3 *tangent = attr_tangent->data_float3();
|
||||||
|
|
||||||
|
for(size_t i = 0; i < mesh->curve_keys.size(); i++)
|
||||||
|
tangent[i] = transform_direction(&tfm, tangent[i]);
|
||||||
|
}
|
||||||
|
|
||||||
if(bounds.valid()) {
|
if(bounds.valid()) {
|
||||||
mesh->compute_bounds();
|
mesh->compute_bounds();
|
||||||
compute_bounds(false, 0.0f);
|
compute_bounds(false, 0.0f);
|
||||||
@@ -133,6 +146,7 @@ void Object::tag_update(Scene *scene)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scene->curve_system_manager->need_update = true;
|
||||||
scene->mesh_manager->need_update = true;
|
scene->mesh_manager->need_update = true;
|
||||||
scene->object_manager->need_update = true;
|
scene->object_manager->need_update = true;
|
||||||
}
|
}
|
||||||
@@ -189,6 +203,20 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
|
|||||||
surface_area += triangle_area(p1, p2, p3);
|
surface_area += triangle_area(p1, p2, p3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach(Mesh::Curve& curve, mesh->curves) {
|
||||||
|
int first_key = curve.first_key;
|
||||||
|
|
||||||
|
for(int i = 0; i < curve.num_segments(); i++) {
|
||||||
|
float3 p1 = mesh->curve_keys[first_key + i].co;
|
||||||
|
float r1 = mesh->curve_keys[first_key + i].radius;
|
||||||
|
float3 p2 = mesh->curve_keys[first_key + i + 1].co;
|
||||||
|
float r2 = mesh->curve_keys[first_key + i + 1].radius;
|
||||||
|
|
||||||
|
/* currently ignores segment overlaps*/
|
||||||
|
surface_area += M_PI_F *(r1 + r2) * len(p1 - p2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
surface_area_map[mesh] = surface_area;
|
surface_area_map[mesh] = surface_area;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -204,6 +232,23 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
|
|||||||
|
|
||||||
surface_area += triangle_area(p1, p2, p3);
|
surface_area += triangle_area(p1, p2, p3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach(Mesh::Curve& curve, mesh->curves) {
|
||||||
|
int first_key = curve.first_key;
|
||||||
|
|
||||||
|
for(int i = 0; i < curve.num_segments(); i++) {
|
||||||
|
float3 p1 = mesh->curve_keys[first_key + i].co;
|
||||||
|
float r1 = mesh->curve_keys[first_key + i].radius;
|
||||||
|
float3 p2 = mesh->curve_keys[first_key + i + 1].co;
|
||||||
|
float r2 = mesh->curve_keys[first_key + i + 1].radius;
|
||||||
|
|
||||||
|
p1 = transform_point(&tfm, p1);
|
||||||
|
p2 = transform_point(&tfm, p2);
|
||||||
|
|
||||||
|
/* currently ignores segment overlaps*/
|
||||||
|
surface_area += M_PI_F *(r1 + r2) * len(p1 - p2);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pack in texture */
|
/* pack in texture */
|
||||||
@@ -355,6 +400,7 @@ void ObjectManager::apply_static_transforms(Scene *scene, uint *object_flag, Pro
|
|||||||
void ObjectManager::tag_update(Scene *scene)
|
void ObjectManager::tag_update(Scene *scene)
|
||||||
{
|
{
|
||||||
need_update = true;
|
need_update = true;
|
||||||
|
scene->curve_system_manager->need_update = true;
|
||||||
scene->mesh_manager->need_update = true;
|
scene->mesh_manager->need_update = true;
|
||||||
scene->light_manager->need_update = true;
|
scene->light_manager->need_update = true;
|
||||||
}
|
}
|
||||||
|
@@ -48,6 +48,7 @@ public:
|
|||||||
MotionTransform motion;
|
MotionTransform motion;
|
||||||
bool use_motion;
|
bool use_motion;
|
||||||
bool use_holdout;
|
bool use_holdout;
|
||||||
|
bool curverender;
|
||||||
|
|
||||||
float3 dupli_generated;
|
float3 dupli_generated;
|
||||||
float2 dupli_uv;
|
float2 dupli_uv;
|
||||||
|
@@ -29,6 +29,7 @@
|
|||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
#include "particles.h"
|
#include "particles.h"
|
||||||
|
#include "curves.h"
|
||||||
#include "scene.h"
|
#include "scene.h"
|
||||||
#include "svm.h"
|
#include "svm.h"
|
||||||
#include "osl.h"
|
#include "osl.h"
|
||||||
@@ -54,6 +55,7 @@ Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_)
|
|||||||
integrator = new Integrator();
|
integrator = new Integrator();
|
||||||
image_manager = new ImageManager();
|
image_manager = new ImageManager();
|
||||||
particle_system_manager = new ParticleSystemManager();
|
particle_system_manager = new ParticleSystemManager();
|
||||||
|
curve_system_manager = new CurveSystemManager();
|
||||||
|
|
||||||
/* OSL only works on the CPU */
|
/* OSL only works on the CPU */
|
||||||
if(device_info_.type == DEVICE_CPU)
|
if(device_info_.type == DEVICE_CPU)
|
||||||
@@ -96,6 +98,7 @@ void Scene::free_memory(bool final)
|
|||||||
light_manager->device_free(device, &dscene);
|
light_manager->device_free(device, &dscene);
|
||||||
|
|
||||||
particle_system_manager->device_free(device, &dscene);
|
particle_system_manager->device_free(device, &dscene);
|
||||||
|
curve_system_manager->device_free(device, &dscene);
|
||||||
|
|
||||||
if(!params.persistent_images || final)
|
if(!params.persistent_images || final)
|
||||||
image_manager->device_free(device, &dscene);
|
image_manager->device_free(device, &dscene);
|
||||||
@@ -112,6 +115,7 @@ void Scene::free_memory(bool final)
|
|||||||
delete shader_manager;
|
delete shader_manager;
|
||||||
delete light_manager;
|
delete light_manager;
|
||||||
delete particle_system_manager;
|
delete particle_system_manager;
|
||||||
|
delete curve_system_manager;
|
||||||
delete image_manager;
|
delete image_manager;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -165,6 +169,11 @@ void Scene::device_update(Device *device_, Progress& progress)
|
|||||||
|
|
||||||
if(progress.get_cancel()) return;
|
if(progress.get_cancel()) return;
|
||||||
|
|
||||||
|
progress.set_status("Updating Hair Systems");
|
||||||
|
curve_system_manager->device_update(device, &dscene, this, progress);
|
||||||
|
|
||||||
|
if(progress.get_cancel()) return;
|
||||||
|
|
||||||
progress.set_status("Updating Meshes");
|
progress.set_status("Updating Meshes");
|
||||||
mesh_manager->device_update(device, &dscene, this, progress);
|
mesh_manager->device_update(device, &dscene, this, progress);
|
||||||
|
|
||||||
@@ -242,7 +251,8 @@ bool Scene::need_reset()
|
|||||||
|| filter->need_update
|
|| filter->need_update
|
||||||
|| integrator->need_update
|
|| integrator->need_update
|
||||||
|| shader_manager->need_update
|
|| shader_manager->need_update
|
||||||
|| particle_system_manager->need_update);
|
|| particle_system_manager->need_update
|
||||||
|
|| curve_system_manager->need_update);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::reset()
|
void Scene::reset()
|
||||||
|
@@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
#include "kernel_types.h"
|
#include "kernel_types.h"
|
||||||
|
|
||||||
#include "util_attribute.h"
|
|
||||||
#include "util_param.h"
|
#include "util_param.h"
|
||||||
#include "util_string.h"
|
#include "util_string.h"
|
||||||
#include "util_thread.h"
|
#include "util_thread.h"
|
||||||
@@ -50,6 +49,7 @@ class Object;
|
|||||||
class ObjectManager;
|
class ObjectManager;
|
||||||
class ParticleSystemManager;
|
class ParticleSystemManager;
|
||||||
class ParticleSystem;
|
class ParticleSystem;
|
||||||
|
class CurveSystemManager;
|
||||||
class Shader;
|
class Shader;
|
||||||
class ShaderManager;
|
class ShaderManager;
|
||||||
class Progress;
|
class Progress;
|
||||||
@@ -62,6 +62,7 @@ public:
|
|||||||
device_vector<float4> bvh_nodes;
|
device_vector<float4> bvh_nodes;
|
||||||
device_vector<uint> object_node;
|
device_vector<uint> object_node;
|
||||||
device_vector<float4> tri_woop;
|
device_vector<float4> tri_woop;
|
||||||
|
device_vector<uint> prim_segment;
|
||||||
device_vector<uint> prim_visibility;
|
device_vector<uint> prim_visibility;
|
||||||
device_vector<uint> prim_index;
|
device_vector<uint> prim_index;
|
||||||
device_vector<uint> prim_object;
|
device_vector<uint> prim_object;
|
||||||
@@ -72,6 +73,9 @@ public:
|
|||||||
device_vector<float4> tri_vindex;
|
device_vector<float4> tri_vindex;
|
||||||
device_vector<float4> tri_verts;
|
device_vector<float4> tri_verts;
|
||||||
|
|
||||||
|
device_vector<float4> curves;
|
||||||
|
device_vector<float4> curve_keys;
|
||||||
|
|
||||||
/* objects */
|
/* objects */
|
||||||
device_vector<float4> objects;
|
device_vector<float4> objects;
|
||||||
device_vector<float4> objects_vector;
|
device_vector<float4> objects_vector;
|
||||||
@@ -170,6 +174,7 @@ public:
|
|||||||
MeshManager *mesh_manager;
|
MeshManager *mesh_manager;
|
||||||
ObjectManager *object_manager;
|
ObjectManager *object_manager;
|
||||||
ParticleSystemManager *particle_system_manager;
|
ParticleSystemManager *particle_system_manager;
|
||||||
|
CurveSystemManager *curve_system_manager;
|
||||||
|
|
||||||
/* default shaders */
|
/* default shaders */
|
||||||
int default_surface;
|
int default_surface;
|
||||||
|
@@ -357,7 +357,7 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile)
|
|||||||
|
|
||||||
tile_lock.unlock();
|
tile_lock.unlock();
|
||||||
|
|
||||||
/* in case of a permant buffer, return it, otherwise we will allocate
|
/* in case of a permanent buffer, return it, otherwise we will allocate
|
||||||
* a new temporary buffer */
|
* a new temporary buffer */
|
||||||
if(!params.background) {
|
if(!params.background) {
|
||||||
tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride);
|
tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride);
|
||||||
@@ -411,6 +411,12 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile)
|
|||||||
rtile.rgba = 0;
|
rtile.rgba = 0;
|
||||||
rtile.buffers = tilebuffers;
|
rtile.buffers = tilebuffers;
|
||||||
|
|
||||||
|
/* this will tag tile as IN PROGRESS in blender-side render pipeline,
|
||||||
|
* which is needed to highlight currently rendering tile before first
|
||||||
|
* sample was processed for it
|
||||||
|
*/
|
||||||
|
update_tile_sample(rtile);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -47,7 +47,7 @@ void EdgeDice::reserve(int num_verts, int num_tris)
|
|||||||
vert_offset = mesh->verts.size();
|
vert_offset = mesh->verts.size();
|
||||||
tri_offset = mesh->triangles.size();
|
tri_offset = mesh->triangles.size();
|
||||||
|
|
||||||
mesh->reserve(vert_offset + num_verts, tri_offset + num_tris);
|
mesh->reserve(vert_offset + num_verts, tri_offset + num_tris, 0, 0);
|
||||||
|
|
||||||
Attribute *attr_vN = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
|
Attribute *attr_vN = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
|
||||||
|
|
||||||
|
@@ -9,7 +9,6 @@ set(INC_SYS
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(SRC
|
set(SRC
|
||||||
util_attribute.cpp
|
|
||||||
util_cache.cpp
|
util_cache.cpp
|
||||||
util_cuda.cpp
|
util_cuda.cpp
|
||||||
util_dynlib.cpp
|
util_dynlib.cpp
|
||||||
@@ -33,7 +32,6 @@ endif()
|
|||||||
set(SRC_HEADERS
|
set(SRC_HEADERS
|
||||||
util_algorithm.h
|
util_algorithm.h
|
||||||
util_args.h
|
util_args.h
|
||||||
util_attribute.h
|
|
||||||
util_boundbox.h
|
util_boundbox.h
|
||||||
util_cache.h
|
util_cache.h
|
||||||
util_cuda.h
|
util_cuda.h
|
||||||
|
@@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011, Blender Foundation.
|
|
||||||
*
|
|
||||||
* 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 2
|
|
||||||
* 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, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "util_attribute.h"
|
|
||||||
|
|
||||||
CCL_NAMESPACE_BEGIN
|
|
||||||
|
|
||||||
const char *attribute_standard_name(AttributeStandard std)
|
|
||||||
{
|
|
||||||
if(std == ATTR_STD_VERTEX_NORMAL)
|
|
||||||
return "N";
|
|
||||||
else if(std == ATTR_STD_FACE_NORMAL)
|
|
||||||
return "Ng";
|
|
||||||
else if(std == ATTR_STD_UV)
|
|
||||||
return "uv";
|
|
||||||
else if(std == ATTR_STD_GENERATED)
|
|
||||||
return "generated";
|
|
||||||
else if(std == ATTR_STD_UV_TANGENT)
|
|
||||||
return "tangent";
|
|
||||||
else if(std == ATTR_STD_UV_TANGENT_SIGN)
|
|
||||||
return "tangent_sign";
|
|
||||||
else if(std == ATTR_STD_POSITION_UNDEFORMED)
|
|
||||||
return "undeformed";
|
|
||||||
else if(std == ATTR_STD_POSITION_UNDISPLACED)
|
|
||||||
return "undisplaced";
|
|
||||||
else if(std == ATTR_STD_MOTION_PRE)
|
|
||||||
return "motion_pre";
|
|
||||||
else if(std == ATTR_STD_MOTION_POST)
|
|
||||||
return "motion_post";
|
|
||||||
else if(std == ATTR_STD_PARTICLE)
|
|
||||||
return "particle";
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
|
@@ -65,6 +65,13 @@ public:
|
|||||||
max = ccl::max(max, pt);
|
max = ccl::max(max, pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__forceinline void grow(const float3& pt, float border)
|
||||||
|
{
|
||||||
|
float3 shift = {border, border, border, 0.0f};
|
||||||
|
min = ccl::min(min, pt - shift);
|
||||||
|
max = ccl::max(max, pt + shift);
|
||||||
|
}
|
||||||
|
|
||||||
__forceinline void grow(const BoundBox& bbox)
|
__forceinline void grow(const BoundBox& bbox)
|
||||||
{
|
{
|
||||||
grow(bbox.min);
|
grow(bbox.min);
|
||||||
|
@@ -448,24 +448,6 @@ __device_inline int4 make_int4(const float3& f)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum AttributeStandard {
|
|
||||||
ATTR_STD_NONE = 0,
|
|
||||||
ATTR_STD_VERTEX_NORMAL,
|
|
||||||
ATTR_STD_FACE_NORMAL,
|
|
||||||
ATTR_STD_UV,
|
|
||||||
ATTR_STD_UV_TANGENT,
|
|
||||||
ATTR_STD_UV_TANGENT_SIGN,
|
|
||||||
ATTR_STD_GENERATED,
|
|
||||||
ATTR_STD_POSITION_UNDEFORMED,
|
|
||||||
ATTR_STD_POSITION_UNDISPLACED,
|
|
||||||
ATTR_STD_MOTION_PRE,
|
|
||||||
ATTR_STD_MOTION_POST,
|
|
||||||
ATTR_STD_PARTICLE,
|
|
||||||
ATTR_STD_NUM,
|
|
||||||
|
|
||||||
ATTR_STD_NOT_FOUND = ~0
|
|
||||||
} AttributeStandard;
|
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
|
||||||
#endif /* __UTIL_TYPES_H__ */
|
#endif /* __UTIL_TYPES_H__ */
|
||||||
|
@@ -1579,7 +1579,13 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
|
|||||||
|
|
||||||
case NSScrollWheel:
|
case NSScrollWheel:
|
||||||
{
|
{
|
||||||
if (!m_hasMultiTouchTrackpad) {
|
int momentum = 0;
|
||||||
|
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
|
||||||
|
m_hasMultiTouchTrackpad = 0;
|
||||||
|
momentum = [event momentumPhase] || [event phase];
|
||||||
|
#endif
|
||||||
|
/* standard scrollwheel case */
|
||||||
|
if (!m_hasMultiTouchTrackpad && momentum == 0) {
|
||||||
GHOST_TInt32 delta;
|
GHOST_TInt32 delta;
|
||||||
|
|
||||||
double deltaF = [event deltaY];
|
double deltaF = [event deltaY];
|
||||||
@@ -1593,9 +1599,18 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
|
|||||||
else {
|
else {
|
||||||
NSPoint mousePos = [cocoawindow mouseLocationOutsideOfEventStream];
|
NSPoint mousePos = [cocoawindow mouseLocationOutsideOfEventStream];
|
||||||
GHOST_TInt32 x, y;
|
GHOST_TInt32 x, y;
|
||||||
double dx = [event deltaX];
|
double dx;
|
||||||
double dy = -[event deltaY];
|
double dy;
|
||||||
|
|
||||||
|
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
|
||||||
|
/* with 10.7 nice scrolling deltas are supported */
|
||||||
|
dx = [event scrollingDeltaX];
|
||||||
|
dy = [event scrollingDeltaY];
|
||||||
|
|
||||||
|
#else
|
||||||
|
/* trying to pretend you have nice scrolls... */
|
||||||
|
dx = [event deltaX];
|
||||||
|
dy = -[event deltaY];
|
||||||
const double deltaMax = 50.0;
|
const double deltaMax = 50.0;
|
||||||
|
|
||||||
if ((dx == 0) && (dy == 0)) break;
|
if ((dx == 0) && (dy == 0)) break;
|
||||||
@@ -1612,9 +1627,10 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
|
|||||||
else dy += 0.5;
|
else dy += 0.5;
|
||||||
if (dy < -deltaMax) dy= -deltaMax;
|
if (dy < -deltaMax) dy= -deltaMax;
|
||||||
else if (dy > deltaMax) dy= deltaMax;
|
else if (dy > deltaMax) dy= deltaMax;
|
||||||
|
|
||||||
window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
|
|
||||||
dy = -dy;
|
dy = -dy;
|
||||||
|
#endif
|
||||||
|
window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
|
||||||
|
|
||||||
pushEvent(new GHOST_EventTrackpad([event timestamp] * 1000, window, GHOST_kTrackpadEventScroll, x, y, dx, dy));
|
pushEvent(new GHOST_EventTrackpad([event timestamp] * 1000, window, GHOST_kTrackpadEventScroll, x, y, dx, dy));
|
||||||
}
|
}
|
||||||
|
@@ -595,6 +595,11 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
|
|||||||
|
|
||||||
[m_window setAcceptsMouseMovedEvents:YES];
|
[m_window setAcceptsMouseMovedEvents:YES];
|
||||||
|
|
||||||
|
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
|
||||||
|
NSView *view = [m_window contentView];
|
||||||
|
[view setAcceptsTouchEvents:YES];
|
||||||
|
#endif
|
||||||
|
|
||||||
[m_window registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType,
|
[m_window registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType,
|
||||||
NSStringPboardType, NSTIFFPboardType, nil]];
|
NSStringPboardType, NSTIFFPboardType, nil]];
|
||||||
|
|
||||||
|
@@ -55,44 +55,49 @@ void bl_locale_set(const char *locale)
|
|||||||
// Specify location of dictionaries.
|
// Specify location of dictionaries.
|
||||||
gen.add_messages_path(messages_path);
|
gen.add_messages_path(messages_path);
|
||||||
gen.add_messages_domain(default_domain);
|
gen.add_messages_domain(default_domain);
|
||||||
//gen.set_default_messages_domain(default_domain);
|
//gen.set_default_messages_domain(default_domain);
|
||||||
|
|
||||||
if (locale && locale[0]) {
|
try {
|
||||||
std::locale::global(gen(locale));
|
if (locale && locale[0]) {
|
||||||
}
|
std::locale::global(gen(locale));
|
||||||
else {
|
}
|
||||||
#if defined (__APPLE__)
|
else {
|
||||||
// workaround to get osx system locale from user defaults
|
#ifdef __APPLE__
|
||||||
FILE* fp;
|
// workaround to get osx system locale from user defaults
|
||||||
std::string locale_osx = "";
|
FILE *fp;
|
||||||
char result[16];
|
std::string locale_osx = "";
|
||||||
int result_len = 0;
|
char result[16];
|
||||||
|
int result_len = 0;
|
||||||
|
|
||||||
fp = popen("defaults read .GlobalPreferences AppleLocale", "r");
|
fp = popen("defaults read .GlobalPreferences AppleLocale", "r");
|
||||||
|
|
||||||
if(fp) {
|
if (fp) {
|
||||||
result_len = fread(result, 1, sizeof(result) - 1, fp);
|
result_len = fread(result, 1, sizeof(result) - 1, fp);
|
||||||
|
|
||||||
if(result_len > 0) {
|
if (result_len > 0) {
|
||||||
result[result_len-1] = '\0'; // \0 terminate and remove \n
|
result[result_len - 1] = '\0'; // \0 terminate and remove \n
|
||||||
locale_osx = std::string(result) + std::string(".UTF-8");
|
locale_osx = std::string(result) + std::string(".UTF-8");
|
||||||
|
}
|
||||||
|
|
||||||
|
pclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
pclose(fp);
|
if (locale_osx == "")
|
||||||
}
|
fprintf(stderr, "Locale set: failed to read AppleLocale read from defaults\n");
|
||||||
|
|
||||||
if(locale_osx == "")
|
std::locale::global(gen(locale_osx.c_str()));
|
||||||
fprintf(stderr, "Locale set: failed to read AppleLocale read from defaults\n");
|
|
||||||
|
|
||||||
std::locale::global(gen(locale_osx.c_str()));
|
|
||||||
#else
|
#else
|
||||||
std::locale::global(gen(""));
|
std::locale::global(gen(""));
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
// Note: boost always uses "C" LC_NUMERIC by default!
|
||||||
|
}
|
||||||
|
catch(std::exception const &e) {
|
||||||
|
std::cout << "bl_locale_set(" << locale << "): " << e.what() << " \n";
|
||||||
}
|
}
|
||||||
// Note: boost always uses "C" LC_NUMERIC by default!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* bl_locale_pgettext(const char *msgctxt, const char *msgid)
|
const char *bl_locale_pgettext(const char *msgctxt, const char *msgid)
|
||||||
{
|
{
|
||||||
// Note: We cannot use short stuff like boost::locale::gettext, because those return
|
// Note: We cannot use short stuff like boost::locale::gettext, because those return
|
||||||
// std::basic_string objects, which c_ptr()-returned char* is no more valid
|
// std::basic_string objects, which c_ptr()-returned char* is no more valid
|
||||||
@@ -107,7 +112,7 @@ const char* bl_locale_pgettext(const char *msgctxt, const char *msgid)
|
|||||||
return msgid;
|
return msgid;
|
||||||
}
|
}
|
||||||
catch(std::exception const &e) {
|
catch(std::exception const &e) {
|
||||||
// std::cout << "boost_locale_pgettext: " << e.what() << " \n";
|
// std::cout << "bl_locale_pgettext(" << msgctxt << ", " << msgid << "): " << e.what() << " \n";
|
||||||
return msgid;
|
return msgid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,7 @@ set(INC
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(INC_SYS
|
set(INC_SYS
|
||||||
../../extern/bullet2/src
|
${BULLET_INCLUDE_DIRS}
|
||||||
${PNG_INCLUDE_DIR}
|
${PNG_INCLUDE_DIR}
|
||||||
${ZLIB_INCLUDE_DIRS}
|
${ZLIB_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
@@ -1 +1 @@
|
|||||||
placeholder
|
placeholder
|
||||||
|
@@ -1 +1 @@
|
|||||||
placeholder
|
placeholder
|
||||||
|
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 3.9 MiB After Width: | Height: | Size: 3.9 MiB |
Binary file not shown.
Before Width: | Height: | Size: 225 KiB After Width: | Height: | Size: 226 KiB |
Binary file not shown.
Before Width: | Height: | Size: 562 KiB After Width: | Height: | Size: 563 KiB |
@@ -81,6 +81,8 @@ LANGUAGES = (
|
|||||||
(35, "Esperanto (Esperanto)", "eo"),
|
(35, "Esperanto (Esperanto)", "eo"),
|
||||||
(36, "Spanish from Spain (Español de España)", "es_ES"),
|
(36, "Spanish from Spain (Español de España)", "es_ES"),
|
||||||
(37, "Amharic (አማርኛ)", "am_ET"),
|
(37, "Amharic (አማርኛ)", "am_ET"),
|
||||||
|
(38, "Uzbek (Oʻzbek)", "uz_UZ"),
|
||||||
|
(39, "Uzbek Cyrillic (Ўзбек)", "uz_UZ@cyrillic"),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Name of language file used by Blender to generate translations' menu.
|
# Name of language file used by Blender to generate translations' menu.
|
||||||
@@ -91,7 +93,7 @@ LANGUAGES_FILE = "languages"
|
|||||||
IMPORT_MIN_LEVEL = -1
|
IMPORT_MIN_LEVEL = -1
|
||||||
|
|
||||||
# Languages in /branches we do not want to import in /trunk currently...
|
# Languages in /branches we do not want to import in /trunk currently...
|
||||||
IMPORT_LANGUAGES_SKIP = {'bg', 'ca', 'fi', 'el', 'ko', 'ne', 'pl', 'ro'}
|
IMPORT_LANGUAGES_SKIP = {'am', 'bg', 'fi', 'el', 'et', 'ko', 'ne', 'pl', 'ro', 'uz', 'uz@cyrillic'}
|
||||||
|
|
||||||
# The comment prefix used in generated messages.txt file.
|
# The comment prefix used in generated messages.txt file.
|
||||||
COMMENT_PREFIX = "#~ "
|
COMMENT_PREFIX = "#~ "
|
||||||
|
@@ -188,6 +188,7 @@ dict_uimsgs = {
|
|||||||
"occluder",
|
"occluder",
|
||||||
"passepartout",
|
"passepartout",
|
||||||
"perspectively",
|
"perspectively",
|
||||||
|
"pixelate",
|
||||||
"polygonization",
|
"polygonization",
|
||||||
"selectability",
|
"selectability",
|
||||||
"slurph",
|
"slurph",
|
||||||
@@ -195,7 +196,7 @@ dict_uimsgs = {
|
|||||||
"symmetrize",
|
"symmetrize",
|
||||||
"trackability",
|
"trackability",
|
||||||
"transmissivity",
|
"transmissivity",
|
||||||
"rasterized", "rasterization",
|
"rasterized", "rasterization", "rasterizer",
|
||||||
"renderer", "renderable", "renderability",
|
"renderer", "renderable", "renderability",
|
||||||
|
|
||||||
# Abbreviations
|
# Abbreviations
|
||||||
@@ -380,6 +381,7 @@ dict_uimsgs = {
|
|||||||
"texface",
|
"texface",
|
||||||
"timeline", "timelines",
|
"timeline", "timelines",
|
||||||
"tosphere",
|
"tosphere",
|
||||||
|
"uilist",
|
||||||
"vcol", "vcols",
|
"vcol", "vcols",
|
||||||
"vgroup", "vgroups",
|
"vgroup", "vgroups",
|
||||||
"vinterlace",
|
"vinterlace",
|
||||||
|
@@ -30,6 +30,9 @@ __all__ = (
|
|||||||
"display_name",
|
"display_name",
|
||||||
"display_name_from_filepath",
|
"display_name_from_filepath",
|
||||||
"ensure_ext",
|
"ensure_ext",
|
||||||
|
"extensions_image",
|
||||||
|
"extensions_movie",
|
||||||
|
"extensions_audio",
|
||||||
"is_subdir",
|
"is_subdir",
|
||||||
"module_names",
|
"module_names",
|
||||||
"relpath",
|
"relpath",
|
||||||
@@ -39,6 +42,10 @@ __all__ = (
|
|||||||
import bpy as _bpy
|
import bpy as _bpy
|
||||||
import os as _os
|
import os as _os
|
||||||
|
|
||||||
|
from _bpy_path import (extensions_audio,
|
||||||
|
extensions_movie,
|
||||||
|
extensions_image,
|
||||||
|
)
|
||||||
|
|
||||||
def abspath(path, start=None, library=None):
|
def abspath(path, start=None, library=None):
|
||||||
"""
|
"""
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user