Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
Diffstat (limited to 'intern')
-rw-r--r--intern/CMakeLists.txt5
-rw-r--r--intern/audaspace/intern/AUD_JOSResampleReader.cpp2
-rw-r--r--intern/cycles/CMakeLists.txt12
-rw-r--r--intern/cycles/SConscript10
-rw-r--r--intern/cycles/app/CMakeLists.txt6
-rw-r--r--intern/cycles/app/cycles_server.cpp6
-rw-r--r--intern/cycles/app/cycles_xml.cpp28
-rw-r--r--intern/cycles/blender/CCL_api.h2
-rw-r--r--intern/cycles/blender/addon/engine.py4
-rw-r--r--intern/cycles/blender/addon/properties.py11
-rw-r--r--intern/cycles/blender/addon/ui.py30
-rw-r--r--intern/cycles/blender/blender_curves.cpp12
-rw-r--r--intern/cycles/blender/blender_mesh.cpp24
-rw-r--r--intern/cycles/blender/blender_object.cpp56
-rw-r--r--intern/cycles/blender/blender_python.cpp40
-rw-r--r--intern/cycles/blender/blender_session.cpp30
-rw-r--r--intern/cycles/device/CMakeLists.txt6
-rw-r--r--intern/cycles/device/device.cpp5
-rw-r--r--intern/cycles/device/device.h2
-rw-r--r--intern/cycles/device/device_cpu.cpp58
-rw-r--r--intern/cycles/device/device_cuda.cpp3
-rw-r--r--intern/cycles/device/device_intern.h2
-rw-r--r--intern/cycles/device/device_multi.cpp9
-rw-r--r--intern/cycles/device/device_network.cpp457
-rw-r--r--intern/cycles/device/device_network.h53
-rw-r--r--intern/cycles/device/device_opencl.cpp3
-rw-r--r--intern/cycles/kernel/CMakeLists.txt9
-rw-r--r--intern/cycles/kernel/closure/volume.h5
-rw-r--r--intern/cycles/kernel/kernel.h9
-rw-r--r--intern/cycles/kernel/kernel_primitive.h19
-rw-r--r--intern/cycles/kernel/kernel_shader.h5
-rw-r--r--intern/cycles/kernel/kernel_sse41.cpp76
-rw-r--r--intern/cycles/kernel/kernel_types.h2
-rw-r--r--intern/cycles/kernel/osl/background.cpp33
-rw-r--r--intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp17
-rw-r--r--intern/cycles/kernel/osl/bsdf_phong_ramp.cpp17
-rw-r--r--intern/cycles/kernel/osl/emissive.cpp15
-rw-r--r--intern/cycles/kernel/osl/osl_bssrdf.cpp32
-rw-r--r--intern/cycles/kernel/osl/osl_bssrdf.h8
-rw-r--r--intern/cycles/kernel/osl/osl_closures.cpp25
-rw-r--r--intern/cycles/kernel/osl/osl_closures.h56
-rw-r--r--intern/cycles/kernel/osl/osl_services.cpp51
-rw-r--r--intern/cycles/kernel/osl/osl_services.h7
-rw-r--r--intern/cycles/kernel/osl/osl_shader.cpp65
-rw-r--r--intern/cycles/kernel/osl/osl_shader.h5
-rw-r--r--intern/cycles/kernel/shaders/stdosl.h16
-rw-r--r--intern/cycles/kernel/svm/svm_fresnel.h12
-rw-r--r--intern/cycles/render/attribute.cpp10
-rw-r--r--intern/cycles/render/nodes.cpp36
-rw-r--r--intern/cycles/render/nodes.h2
-rw-r--r--intern/cycles/render/osl.cpp36
-rw-r--r--intern/cycles/render/osl.h4
-rw-r--r--intern/cycles/render/session.cpp18
-rw-r--r--intern/cycles/subd/CMakeLists.txt9
-rw-r--r--intern/cycles/subd/subd_build.cpp669
-rw-r--r--intern/cycles/subd/subd_build.h73
-rw-r--r--intern/cycles/subd/subd_dice.cpp100
-rw-r--r--intern/cycles/subd/subd_dice.h42
-rw-r--r--intern/cycles/subd/subd_edge.h70
-rw-r--r--intern/cycles/subd/subd_face.h109
-rw-r--r--intern/cycles/subd/subd_mesh.cpp493
-rw-r--r--intern/cycles/subd/subd_mesh.h40
-rw-r--r--intern/cycles/subd/subd_patch.cpp163
-rw-r--r--intern/cycles/subd/subd_patch.h40
-rw-r--r--intern/cycles/subd/subd_ring.cpp236
-rw-r--r--intern/cycles/subd/subd_ring.h75
-rw-r--r--intern/cycles/subd/subd_split.cpp31
-rw-r--r--intern/cycles/subd/subd_split.h11
-rw-r--r--intern/cycles/subd/subd_stencil.cpp101
-rw-r--r--intern/cycles/subd/subd_stencil.h65
-rw-r--r--intern/cycles/subd/subd_vert.h121
-rw-r--r--intern/cycles/util/util_math.h13
-rw-r--r--intern/cycles/util/util_string.cpp19
-rw-r--r--intern/cycles/util/util_string.h2
-rw-r--r--intern/cycles/util/util_system.cpp9
-rw-r--r--intern/cycles/util/util_system.h1
-rw-r--r--intern/cycles/util/util_types.h28
-rw-r--r--intern/elbeem/intern/ntl_blenderdumper.cpp2
-rw-r--r--intern/elbeem/intern/particletracer.cpp2
-rw-r--r--intern/guardedalloc/intern/mmap_win.c14
-rw-r--r--intern/itasc/Armature.cpp2
-rw-r--r--intern/itasc/kdl/tree.cpp2
-rw-r--r--intern/itasc/kdl/tree.hpp24
-rw-r--r--intern/itasc/kdl/treefksolverpos_recursive.cpp17
-rw-r--r--intern/itasc/kdl/treefksolverpos_recursive.hpp2
-rw-r--r--intern/itasc/kdl/treejnttojacsolver.cpp6
-rw-r--r--intern/locale/SConscript4
-rw-r--r--intern/memutil/MEM_CacheLimiter.h105
-rw-r--r--intern/opencolorio/fallback_impl.cc10
-rw-r--r--intern/opencolorio/ocio_capi.cc10
-rw-r--r--intern/opencolorio/ocio_capi.h3
-rw-r--r--intern/opencolorio/ocio_impl.cc10
-rw-r--r--intern/opencolorio/ocio_impl.h9
93 files changed, 1640 insertions, 2568 deletions
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt
index c45e66cd77b..b7aff03a710 100644
--- a/intern/CMakeLists.txt
+++ b/intern/CMakeLists.txt
@@ -29,7 +29,6 @@ add_subdirectory(ghost)
add_subdirectory(guardedalloc)
add_subdirectory(memutil)
add_subdirectory(opencolorio)
-add_subdirectory(opennl)
add_subdirectory(mikktspace)
add_subdirectory(raskter)
@@ -81,6 +80,10 @@ if(WITH_COMPOSITOR)
add_subdirectory(opencl)
endif()
+if(WITH_OPENNL)
+ add_subdirectory(opennl)
+endif()
+
# only windows needs utf16 converter
if(WIN32)
add_subdirectory(utfconv)
diff --git a/intern/audaspace/intern/AUD_JOSResampleReader.cpp b/intern/audaspace/intern/AUD_JOSResampleReader.cpp
index 87577da95cc..0448c75d777 100644
--- a/intern/audaspace/intern/AUD_JOSResampleReader.cpp
+++ b/intern/audaspace/intern/AUD_JOSResampleReader.cpp
@@ -36,6 +36,7 @@
/* MSVC does not have lrint */
#ifdef _MSC_VER
+#if _MSC_VER < 1800
#ifdef _M_X64
#include <emmintrin.h>
static inline int lrint(double d)
@@ -56,6 +57,7 @@ static inline int lrint(double d)
}
#endif
#endif
+#endif
// UNUSED
// #define CC m_channels + channel
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt
index 6821e93ad87..fc193d99a57 100644
--- a/intern/cycles/CMakeLists.txt
+++ b/intern/cycles/CMakeLists.txt
@@ -17,9 +17,11 @@ if(WIN32 AND MSVC)
if(CMAKE_CL_64)
set(CYCLES_SSE2_KERNEL_FLAGS "/fp:fast -D_CRT_SECURE_NO_WARNINGS /Gs-")
set(CYCLES_SSE3_KERNEL_FLAGS "/fp:fast -D_CRT_SECURE_NO_WARNINGS /Gs-")
+ set(CYCLES_SSE41_KERNEL_FLAGS "/fp:fast -D_CRT_SECURE_NO_WARNINGS /Gs-")
else()
set(CYCLES_SSE2_KERNEL_FLAGS "/arch:SSE2 /fp:fast -D_CRT_SECURE_NO_WARNINGS /Gs-")
set(CYCLES_SSE3_KERNEL_FLAGS "/arch:SSE2 /fp:fast -D_CRT_SECURE_NO_WARNINGS /Gs-")
+ set(CYCLES_SSE41_KERNEL_FLAGS "/arch:SSE2 /fp:fast -D_CRT_SECURE_NO_WARNINGS /Gs-")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fp:fast -D_CRT_SECURE_NO_WARNINGS /Gs-")
@@ -29,10 +31,12 @@ if(WIN32 AND MSVC)
elseif(CMAKE_COMPILER_IS_GNUCC)
set(CYCLES_SSE2_KERNEL_FLAGS "-ffast-math -msse -msse2 -mfpmath=sse")
set(CYCLES_SSE3_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse")
+ set(CYCLES_SSE41_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mfpmath=sse")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CYCLES_SSE2_KERNEL_FLAGS "-ffast-math -msse -msse2")
set(CYCLES_SSE3_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3")
+ set(CYCLES_SSE41_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math")
endif()
@@ -58,6 +62,14 @@ if(WITH_CYCLES_NETWORK)
add_definitions(-DWITH_NETWORK)
endif()
+if(WITH_CYCLES_PTEX)
+ add_definitions(-DWITH_PTEX)
+endif()
+
+if(WITH_CYCLES_OPENSUBDIV)
+ add_definitions(-DWITH_OPENSUBDIV)
+endif()
+
if(WITH_CYCLES_OSL)
add_definitions(-DWITH_OSL)
add_definitions(-DOSL_STATIC_LIBRARY)
diff --git a/intern/cycles/SConscript b/intern/cycles/SConscript
index e61018bc3dd..eeb60f37f92 100644
--- a/intern/cycles/SConscript
+++ b/intern/cycles/SConscript
@@ -37,6 +37,7 @@ sources = cycles.Glob('bvh/*.cpp') + cycles.Glob('device/*.cpp') + cycles.Glob('
sources.remove(path.join('util', 'util_view.cpp'))
sources.remove(path.join('kernel', 'kernel_sse2.cpp'))
sources.remove(path.join('kernel', 'kernel_sse3.cpp'))
+sources.remove(path.join('kernel', 'kernel_sse41.cpp'))
incs = []
defs = []
@@ -77,21 +78,30 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', '
if env['WITH_BF_RAYOPTIMIZATION']:
sse2_cxxflags = Split(env['CXXFLAGS'])
sse3_cxxflags = Split(env['CXXFLAGS'])
+ sse41_cxxflags = Split(env['CXXFLAGS'])
if env['OURPLATFORM'] == 'win32-vc':
# there is no /arch:SSE3, but intrinsics are available anyway
sse2_cxxflags.append('/arch:SSE /arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /fp:fast /Ox /Gs-'.split())
sse3_cxxflags.append('/arch:SSE /arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /fp:fast /Ox /Gs-'.split())
+ sse41_cxxflags.append('/arch:SSE /arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /fp:fast /Ox /Gs-'.split())
elif env['OURPLATFORM'] == 'win64-vc':
sse2_cxxflags.append('-D_CRT_SECURE_NO_WARNINGS /fp:fast /Ox /Gs-'.split())
sse3_cxxflags.append('-D_CRT_SECURE_NO_WARNINGS /fp:fast /Ox /Gs-'.split())
+ sse41_cxxflags.append('-D_CRT_SECURE_NO_WARNINGS /fp:fast /Ox /Gs-'.split())
else:
sse2_cxxflags.append('-ffast-math -msse -msse2 -mfpmath=sse'.split())
sse3_cxxflags.append('-ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse'.split())
+ sse41_cxxflags.append('-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mfpmath=sse'.split())
defs.append('WITH_OPTIMIZED_KERNEL')
optim_defs = defs[:]
+ # Disabled sse4+ patchs for now
+ #cycles_sse41 = cycles.Clone()
+ #sse41_sources = [path.join('kernel', 'kernel_sse41.cpp')]
+ #cycles_sse41.BlenderLib('bf_intern_cycles_sse41', sse41_sources, incs, optim_defs, libtype=['intern'], priority=[10], cxx_compileflags=sse41_cxxflags)
+
cycles_sse3 = cycles.Clone()
sse3_sources = [path.join('kernel', 'kernel_sse3.cpp')]
cycles_sse3.BlenderLib('bf_intern_cycles_sse3', sse3_sources, incs, optim_defs, libtype=['intern'], priority=[10], cxx_compileflags=sse3_cxxflags)
diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt
index a2142d77a9e..8a81ddde1e1 100644
--- a/intern/cycles/app/CMakeLists.txt
+++ b/intern/cycles/app/CMakeLists.txt
@@ -30,6 +30,10 @@ set(LIBRARIES
${TIFF_LIBRARY}
)
+if(UNIX)
+ list(APPEND LIBRARIES dl)
+endif()
+
if(WIN32)
list(APPEND LIBRARIES ${PTHREADS_LIBRARIES})
endif()
@@ -41,7 +45,7 @@ if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
endif()
if(WITH_CYCLES_OSL)
- list(APPEND LIBRARIES cycles_kernel_osl ${OSL_LIBRARIES})
+ list(APPEND LIBRARIES cycles_kernel_osl ${OSL_LIBRARIES} ${LLVM_LIBRARY})
endif()
include_directories(${INC})
diff --git a/intern/cycles/app/cycles_server.cpp b/intern/cycles/app/cycles_server.cpp
index e80fc0cb95f..f4cacb2d001 100644
--- a/intern/cycles/app/cycles_server.cpp
+++ b/intern/cycles/app/cycles_server.cpp
@@ -35,6 +35,7 @@ int main(int argc, const char **argv)
string devicelist = "";
string devicename = "cpu";
bool list = false;
+ int threads = 0;
vector<DeviceType>& types = Device::available_types();
@@ -51,6 +52,7 @@ int main(int argc, const char **argv)
ap.options ("Usage: cycles_server [options]",
"--device %s", &devicename, ("Devices to use: " + devicelist).c_str(),
"--list-devices", &list, "List information about all available devices",
+ "--threads %d", &threads, "Number of threads to use for CPU device",
NULL);
if(ap.parse(argc, argv) < 0) {
@@ -84,11 +86,11 @@ int main(int argc, const char **argv)
}
}
- TaskScheduler::init();
+ TaskScheduler::init(threads);
while(1) {
Stats stats;
- Device *device = Device::create(device_info, stats);
+ Device *device = Device::create(device_info, stats, true);
printf("Cycles Server with device: %s\n", device->info.description.c_str());
device->server_run();
delete device;
diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp
index 55a2a30b9a8..df187f046e5 100644
--- a/intern/cycles/app/cycles_xml.cpp
+++ b/intern/cycles/app/cycles_xml.cpp
@@ -703,15 +703,14 @@ static void xml_read_mesh(const XMLReadState& state, pugi::xml_node node)
}
/* finalize subd mesh */
- sdmesh.link_boundary();
-
- /* subdivide */
- DiagSplit dsplit;
- //dsplit.camera = state.scene->camera;
- //dsplit.dicing_rate = 5.0f;
- dsplit.dicing_rate = state.dicing_rate;
- xml_read_float(&dsplit.dicing_rate, node, "dicing_rate");
- sdmesh.tessellate(&dsplit, false, mesh, shader, smooth);
+ sdmesh.finish();
+
+ /* parameters */
+ SubdParams sdparams(mesh, shader, smooth);
+ xml_read_float(&sdparams.dicing_rate, node, "dicing_rate");
+
+ DiagSplit dsplit(sdparams);;
+ sdmesh.tessellate(&dsplit);
}
else {
/* create vertices */
@@ -789,12 +788,11 @@ static void xml_read_patch(const XMLReadState& state, pugi::xml_node node)
mesh->used_shaders.push_back(state.shader);
/* split */
- DiagSplit dsplit;
- //dsplit.camera = state.scene->camera;
- //dsplit.dicing_rate = 5.0f;
- dsplit.dicing_rate = state.dicing_rate;
- xml_read_float(&dsplit.dicing_rate, node, "dicing_rate");
- dsplit.split_quad(mesh, patch, state.shader, state.smooth);
+ SubdParams sdparams(mesh, state.shader, state.smooth);
+ xml_read_float(&sdparams.dicing_rate, node, "dicing_rate");
+
+ DiagSplit dsplit(sdparams);
+ dsplit.split_quad(patch);
delete patch;
diff --git a/intern/cycles/blender/CCL_api.h b/intern/cycles/blender/CCL_api.h
index 29d8ed0d98e..6532315cf39 100644
--- a/intern/cycles/blender/CCL_api.h
+++ b/intern/cycles/blender/CCL_api.h
@@ -30,7 +30,7 @@ typedef struct CCLDeviceInfo {
int value;
} CCLDeviceInfo;
-CCLDeviceInfo *CCL_compute_device_list(int opencl);
+CCLDeviceInfo *CCL_compute_device_list(int device_type);
/* create python module _cycles used by addon */
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index 3f15e232de7..66dc5e78e5a 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -88,3 +88,7 @@ def available_devices():
def with_osl():
import _cycles
return _cycles.with_osl
+
+def with_network():
+ import _cycles
+ return _cycles.with_network
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index ac15acee0c5..f5c052e7f0c 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -25,9 +25,15 @@ from bpy.props import (BoolProperty,
# enums
+import _cycles
+
enum_devices = (
- ('CPU', "CPU", "Use CPU for rendering"),
- ('GPU', "GPU Compute", "Use GPU compute device for rendering, configured in user preferences"))
+ ('CPU', "CPU", "Use CPU for rendering"),
+ ('GPU', "GPU Compute", "Use GPU compute device for rendering, configured in user preferences"),
+ )
+
+if _cycles.with_network:
+ enum_devices += (('NETWORK', "Networked Device", "Use networked device for rendering"),)
enum_feature_set = (
('SUPPORTED', "Supported", "Only use finished and supported features"),
@@ -621,6 +627,7 @@ class CyclesVisibilitySettings(bpy.types.PropertyGroup):
@classmethod
def unregister(cls):
del bpy.types.Object.cycles_visibility
+ del bpy.types.World.cycles_visibility
class CyclesMeshSettings(bpy.types.PropertyGroup):
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index cbf26fb8d0a..05d3c15d076 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -311,31 +311,6 @@ class CyclesRender_PT_opengl(CyclesButtonsPanel, Panel):
col.prop(rd, "alpha_mode", text="")
-class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
- bl_label = "Layer List"
- bl_context = "render_layer"
- bl_options = {'HIDE_HEADER'}
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- rd = scene.render
- rl = rd.layers.active
-
- row = layout.row()
- row.template_list("RENDERLAYER_UL_renderlayers", "", rd, "layers", rd.layers, "active_index", rows=1)
-
- col = row.column(align=True)
- col.operator("scene.render_layer_add", icon='ZOOMIN', text="")
- col.operator("scene.render_layer_remove", icon='ZOOMOUT', text="")
-
- row = layout.row()
- if rl:
- row.prop(rl, "name")
- row.prop(rd, "use_single_layer", text="", icon_only=True)
-
-
class CyclesRender_PT_layer_options(CyclesButtonsPanel, Panel):
bl_label = "Layer"
bl_context = "render_layer"
@@ -1275,9 +1250,7 @@ def draw_device(self, context):
layout.prop(cscene, "feature_set")
device_type = context.user_preferences.system.compute_device_type
- if device_type == 'CUDA':
- layout.prop(cscene, "device")
- elif device_type == 'OPENCL':
+ if device_type in {'CUDA', 'OPENCL', 'NETWORK'}:
layout.prop(cscene, "device")
if engine.with_osl() and (cscene.device == 'CPU' or device_type == 'NONE'):
@@ -1306,6 +1279,7 @@ def get_panels():
types.RENDER_PT_encoding,
types.RENDER_PT_dimensions,
types.RENDER_PT_stamp,
+ types.RENDERLAYER_PT_layers,
types.SCENE_PT_scene,
types.SCENE_PT_color_management,
types.SCENE_PT_custom_props,
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index b780877a158..da4acf16a4d 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -400,6 +400,8 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, float3 RotC
for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
+ if(CData->curve_length[curve] == 0.0f)
+ continue;
float3 xbasis;
float3 v1;
@@ -460,6 +462,8 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int resol
for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
+ if(CData->curve_length[curve] == 0.0f)
+ continue;
float3 firstxbasis = cross(make_float3(1.0f,0.0f,0.0f),CData->curvekey_co[CData->curve_firstkey[curve]+1] - CData->curvekey_co[CData->curve_firstkey[curve]]);
if(len_squared(firstxbasis)!= 0.0f)
@@ -593,7 +597,7 @@ void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData)
for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
- if(CData->curve_keynum[curve] <= 1)
+ if(CData->curve_keynum[curve] <= 1 || CData->curve_length[curve] == 0.0f)
continue;
size_t num_curve_keys = 0;
@@ -644,7 +648,7 @@ static void ExportCurveSegmentsMotion(Scene *scene, Mesh *mesh, ParticleCurveDat
continue;
for(int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; curve++) {
- if(CData->curve_keynum[curve] <= 1)
+ if(CData->curve_keynum[curve] <= 1 || CData->curve_length[curve] == 0.0f)
continue;
for(int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve]; curvekey++) {
@@ -683,6 +687,8 @@ void ExportCurveTriangleUV(Mesh *mesh, ParticleCurveData *CData, int vert_offset
for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+ if(CData->curve_length[curve] == 0.0f)
+ continue;
time = CData->curvekey_time[curvekey]/CData->curve_length[curve];
@@ -724,6 +730,8 @@ void ExportCurveTriangleVcol(Mesh *mesh, ParticleCurveData *CData, int vert_offs
for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
+ if(CData->curve_length[curve] == 0.0f)
+ continue;
for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index e42af60c27b..0e46903a50c 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -365,7 +365,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
}
}
-static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, const vector<uint>& used_shaders)
+static void create_subd_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, const vector<uint>& used_shaders)
{
/* create subd mesh */
SubdMesh sdmesh;
@@ -386,21 +386,25 @@ static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, con
if(n == 4)
sdmesh.add_face(vi[0], vi[1], vi[2], vi[3]);
-#if 0
else
sdmesh.add_face(vi[0], vi[1], vi[2]);
-#endif
}
/* finalize subd mesh */
- sdmesh.link_boundary();
+ sdmesh.finish();
- /* subdivide */
- DiagSplit dsplit;
- dsplit.camera = NULL;
- dsplit.dicing_rate = RNA_float_get(cmesh, "dicing_rate");
+ /* parameters */
+ bool need_ptex = mesh->need_attribute(scene, ATTR_STD_PTEX_FACE_ID) ||
+ mesh->need_attribute(scene, ATTR_STD_PTEX_UV);
- sdmesh.tessellate(&dsplit, false, mesh, used_shaders[0], true);
+ SubdParams sdparams(mesh, used_shaders[0], true, need_ptex);
+ sdparams.dicing_rate = RNA_float_get(cmesh, "dicing_rate");
+ //scene->camera->update();
+ //sdparams.camera = scene->camera;
+
+ /* tesselate */
+ DiagSplit dsplit(sdparams);;
+ sdmesh.tessellate(&dsplit);
}
/* Sync */
@@ -482,7 +486,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri
if(b_mesh) {
if(render_layer.use_surfaces && !hide_tris) {
if(cmesh.data && experimental && RNA_boolean_get(&cmesh, "use_subdivision"))
- create_subd_mesh(mesh, b_mesh, &cmesh, used_shaders);
+ create_subd_mesh(scene, mesh, b_mesh, &cmesh, used_shaders);
else
create_mesh(scene, mesh, b_mesh, used_shaders);
}
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index ba584e172dc..0df8939bc18 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -267,13 +267,38 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P
/* mesh sync */
object->mesh = sync_mesh(b_ob, object_updated, hide_tris);
- /* sspecial case not tracked by object update flags */
+ /* special case not tracked by object update flags */
+
+ /* holdout */
if(use_holdout != object->use_holdout) {
object->use_holdout = use_holdout;
scene->object_manager->tag_update(scene);
object_updated = true;
}
+ /* visibility flags for both parent and child */
+ uint visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL_VISIBILITY;
+ if(b_parent.ptr.data != b_ob.ptr.data) {
+ visibility &= object_ray_visibility(b_parent);
+ object->random_id ^= hash_int(hash_string(b_parent.name().c_str()));
+ }
+
+ /* make holdout objects on excluded layer invisible for non-camera rays */
+ if(use_holdout && (layer_flag & render_layer.exclude_layer))
+ visibility &= ~(PATH_RAY_ALL_VISIBILITY - PATH_RAY_CAMERA);
+
+ /* camera flag is not actually used, instead is tested against render layer
+ * flags */
+ if(visibility & PATH_RAY_CAMERA) {
+ visibility |= layer_flag << PATH_RAY_LAYER_SHIFT;
+ visibility &= ~PATH_RAY_CAMERA;
+ }
+
+ if(visibility != object->visibility) {
+ object->visibility = visibility;
+ object_updated = true;
+ }
+
/* object sync
* transform comparison should not be needed, but duplis don't work perfect
* in the depsgraph and may not signal changes, so this is a workaround */
@@ -295,24 +320,10 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P
else
object->random_id = hash_int_2d(object->random_id, 0);
- /* visibility flags for both parent */
- object->visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL_VISIBILITY;
- if(b_parent.ptr.data != b_ob.ptr.data) {
- object->visibility &= object_ray_visibility(b_parent);
+ if(b_parent.ptr.data != b_ob.ptr.data)
object->random_id ^= hash_int(hash_string(b_parent.name().c_str()));
- }
-
- /* make holdout objects on excluded layer invisible for non-camera rays */
- if(use_holdout && (layer_flag & render_layer.exclude_layer))
- object->visibility &= ~(PATH_RAY_ALL_VISIBILITY - PATH_RAY_CAMERA);
-
- /* camera flag is not actually used, instead is tested
- * against render layer flags */
- if(object->visibility & PATH_RAY_CAMERA) {
- object->visibility |= layer_flag << PATH_RAY_LAYER_SHIFT;
- object->visibility &= ~PATH_RAY_CAMERA;
- }
+ /* dupli texture coordinates */
if (b_dupli_ob) {
object->dupli_generated = 0.5f*get_float3(b_dupli_ob.orco()) - make_float3(0.5f, 0.5f, 0.5f);
object->dupli_uv = get_float2(b_dupli_ob.uv());
@@ -346,6 +357,7 @@ static bool object_render_hide(BL::Object b_ob, bool top_level, bool parent_hide
bool hair_present = false;
bool show_emitter = false;
+ bool hide_emitter = false;
bool hide_as_dupli_parent = false;
bool hide_as_dupli_child_original = false;
@@ -356,8 +368,13 @@ static bool object_render_hide(BL::Object b_ob, bool top_level, bool parent_hide
if(b_psys->settings().use_render_emitter())
show_emitter = true;
+ else
+ hide_emitter = true;
}
+ if(show_emitter)
+ hide_emitter = false;
+
/* duplicators hidden by default, except dupliframes which duplicate self */
if(b_ob.is_duplicator())
if(top_level || b_ob.dupli_type() != BL::Object::dupli_type_FRAMES)
@@ -369,16 +386,15 @@ static bool object_render_hide(BL::Object b_ob, bool top_level, bool parent_hide
if(parent_hide)
hide_as_dupli_child_original = true;
+ hide_triangles = hide_emitter;
+
if(show_emitter) {
- hide_triangles = false;
return false;
}
else if(hair_present) {
- hide_triangles = true;
return hide_as_dupli_child_original;
}
else {
- hide_triangles = false;
return (hide_as_dupli_parent || hide_as_dupli_child_original);
}
}
diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp
index 71c84869ff6..22c425aa332 100644
--- a/intern/cycles/blender/blender_python.cpp
+++ b/intern/cycles/blender/blender_python.cpp
@@ -475,19 +475,55 @@ void *CCL_python_module_init()
PyObject *mod = PyModule_Create(&ccl::module);
#ifdef WITH_OSL
+ /* TODO(sergey): This gives us library we've been linking against.
+ * In theory with dynamic OSL library it might not be
+ * accurate, but there's nothing in OSL API which we
+ * might use th get version in runtime.
+ */
+ int curversion = OSL_LIBRARY_VERSION_CODE;
PyModule_AddObject(mod, "with_osl", Py_True);
Py_INCREF(Py_True);
+ PyModule_AddObject(mod, "osl_version",
+ Py_BuildValue("(iii)",
+ curversion / 10000, (curversion / 100) % 100, curversion % 100));
+ PyModule_AddObject(mod, "osl_version_string",
+ PyUnicode_FromFormat("%2d, %2d, %2d",
+ curversion / 10000, (curversion / 100) % 100, curversion % 100));
#else
PyModule_AddObject(mod, "with_osl", Py_False);
Py_INCREF(Py_False);
+ PyModule_AddStringConstant(mod, "osl_version", "unknown");
+ PyModule_AddStringConstant(mod, "osl_version_string", "unknown");
#endif
+#ifdef WITH_NETWORK
+ PyModule_AddObject(mod, "with_network", Py_True);
+ Py_INCREF(Py_True);
+#else /* WITH_NETWORK */
+ PyModule_AddObject(mod, "with_network", Py_False);
+ Py_INCREF(Py_False);
+#endif /* WITH_NETWORK */
+
return (void*)mod;
}
-CCLDeviceInfo *CCL_compute_device_list(int opencl)
+CCLDeviceInfo *CCL_compute_device_list(int device_type)
{
- ccl::DeviceType type = (opencl)? ccl::DEVICE_OPENCL: ccl::DEVICE_CUDA;
+ ccl::DeviceType type;
+ switch(device_type) {
+ case 0:
+ type = ccl::DEVICE_CUDA;
+ break;
+ case 1:
+ type = ccl::DEVICE_OPENCL;
+ break;
+ case 2:
+ type = ccl::DEVICE_NETWORK;
+ break;
+ default:
+ type = ccl::DEVICE_NONE;
+ break;
+ }
return ccl::compute_device_list(type);
}
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index 84ff071171b..db673a8d625 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -625,28 +625,42 @@ void BlenderSession::get_progress(float& progress, double& total_time)
void BlenderSession::update_status_progress()
{
string timestatus, status, substatus;
+ string scene = "";
float progress;
- double total_time;
+ double total_time, remaining_time = 0;
char time_str[128];
float mem_used = (float)session->stats.mem_used / 1024.0f / 1024.0f;
float mem_peak = (float)session->stats.mem_peak / 1024.0f / 1024.0f;
+ int samples = session->tile_manager.state.sample + 1;
+ int total_samples = session->tile_manager.num_samples;
get_status(status, substatus);
get_progress(progress, total_time);
- timestatus = string_printf("Mem:%.2fM, Peak:%.2fM", mem_used, mem_peak);
+
if(background) {
- timestatus += " | " + b_scene.name();
+ if(progress>0)
+ remaining_time = (1-progress) * (total_time / progress);
+
+ scene += " | " + b_scene.name();
if(b_rlay_name != "")
- timestatus += ", " + b_rlay_name;
+ scene += ", " + b_rlay_name;
}
else {
- timestatus += " | ";
-
BLI_timestr(total_time, time_str, sizeof(time_str));
- timestatus += "Time:" + string(time_str);
+ timestatus = "Time:" + string(time_str) + " | ";
+
+ if(samples > 0 && total_samples != USHRT_MAX)
+ remaining_time = (total_samples - samples) * (total_time / samples);
}
+
+ if(remaining_time>0) {
+ BLI_timestr(remaining_time, time_str, sizeof(time_str));
+ timestatus += "Remaining:" + string(time_str) + " | ";
+ }
+
+ timestatus += string_printf("Mem:%.2fM, Peak:%.2fM", mem_used, mem_peak);
if(status.size() > 0)
status = " | " + status;
@@ -654,12 +668,12 @@ void BlenderSession::update_status_progress()
status += " | " + substatus;
if(status != last_status) {
- b_engine.update_stats("", (timestatus + status).c_str());
b_engine.update_memory_stats(mem_used, mem_peak);
last_status = status;
}
if(progress != last_progress) {
b_engine.update_progress(progress);
+ b_engine.update_stats("", (timestatus + scene + status).c_str());
last_progress = progress;
}
}
diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt
index fe2368b7ea8..825e82209aa 100644
--- a/intern/cycles/device/CMakeLists.txt
+++ b/intern/cycles/device/CMakeLists.txt
@@ -13,6 +13,10 @@ set(INC_SYS
${GLEW_INCLUDE_PATH}
)
+if(WITH_CYCLES_OPTIMIZED_KERNEL_SSE41)
+ add_definitions(-DWITH_CYCLES_OPTIMIZED_KERNEL_SSE41=1)
+endif()
+
set(SRC
device.cpp
device_cpu.cpp
@@ -22,7 +26,7 @@ set(SRC
device_task.cpp
)
-if(WITH_NETWORK)
+if(WITH_CYCLES_NETWORK)
list(APPEND SRC
device_network.cpp
)
diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp
index 5c771aa1c8b..6283e34f563 100644
--- a/intern/cycles/device/device.cpp
+++ b/intern/cycles/device/device.cpp
@@ -127,7 +127,7 @@ Device *Device::create(DeviceInfo& info, Stats &stats, bool background)
switch(info.type) {
case DEVICE_CPU:
- device = device_cpu_create(info, stats);
+ device = device_cpu_create(info, stats, background);
break;
#ifdef WITH_CUDA
case DEVICE_CUDA:
@@ -159,9 +159,6 @@ Device *Device::create(DeviceInfo& info, Stats &stats, bool background)
return NULL;
}
- if(device)
- device->info = info;
-
return device;
}
diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h
index 18868d19a85..bd309e35788 100644
--- a/intern/cycles/device/device.h
+++ b/intern/cycles/device/device.h
@@ -71,7 +71,7 @@ public:
class Device {
protected:
- Device(Stats &stats_) : stats(stats_) {}
+ Device(DeviceInfo& info_, Stats &stats_, bool background) : background(background), info(info_), stats(stats_) {}
bool background;
string error_msg;
diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp
index d04c5df82fb..e084116c72d 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -45,11 +45,13 @@ class CPUDevice : public Device
public:
TaskPool task_pool;
KernelGlobals kernel_globals;
+
#ifdef WITH_OSL
OSLGlobals osl_globals;
#endif
- CPUDevice(Stats &stats) : Device(stats)
+ CPUDevice(DeviceInfo& info, Stats &stats, bool background)
+ : Device(info, stats, background)
{
#ifdef WITH_OSL
kernel_globals.osl = &osl_globals;
@@ -58,6 +60,7 @@ public:
/* do now to avoid thread issues */
system_cpu_support_sse2();
system_cpu_support_sse3();
+ system_cpu_support_sse41();
}
~CPUDevice()
@@ -164,6 +167,28 @@ public:
int end_sample = tile.start_sample + tile.num_samples;
#ifdef WITH_OPTIMIZED_KERNEL
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
+ if(system_cpu_support_sse41()) {
+ for(int sample = start_sample; sample < end_sample; sample++) {
+ if (task.get_cancel() || task_pool.canceled()) {
+ if(task.need_finish_queue == false)
+ break;
+ }
+
+ for(int y = tile.y; y < tile.y + tile.h; y++) {
+ for(int x = tile.x; x < tile.x + tile.w; x++) {
+ kernel_cpu_sse41_path_trace(&kg, render_buffer, rng_state,
+ sample, x, y, tile.offset, tile.stride);
+ }
+ }
+
+ tile.sample = sample + 1;
+
+ task.update_progress(tile);
+ }
+ }
+ else
+#endif
if(system_cpu_support_sse3()) {
for(int sample = start_sample; sample < end_sample; sample++) {
if (task.get_cancel() || task_pool.canceled()) {
@@ -243,6 +268,15 @@ public:
if(task.rgba_half) {
#ifdef WITH_OPTIMIZED_KERNEL
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
+ if(system_cpu_support_sse41()) {
+ for(int y = task.y; y < task.y + task.h; y++)
+ for(int x = task.x; x < task.x + task.w; x++)
+ kernel_cpu_sse41_convert_to_half_float(&kernel_globals, (uchar4*)task.rgba_half, (float*)task.buffer,
+ sample_scale, x, y, task.offset, task.stride);
+ }
+ else
+#endif
if(system_cpu_support_sse3()) {
for(int y = task.y; y < task.y + task.h; y++)
for(int x = task.x; x < task.x + task.w; x++)
@@ -266,6 +300,14 @@ public:
}
else {
#ifdef WITH_OPTIMIZED_KERNEL
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
+ if(system_cpu_support_sse41()) {
+ for(int y = task.y; y < task.y + task.h; y++)
+ for(int x = task.x; x < task.x + task.w; x++)
+ kernel_cpu_sse41_convert_to_byte(&kernel_globals, (uchar4*)task.rgba_byte, (float*)task.buffer,
+ sample_scale, x, y, task.offset, task.stride);
+ }
+#endif
if(system_cpu_support_sse3()) {
for(int y = task.y; y < task.y + task.h; y++)
for(int x = task.x; x < task.x + task.w; x++)
@@ -298,6 +340,16 @@ public:
#endif
#ifdef WITH_OPTIMIZED_KERNEL
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
+ if(system_cpu_support_sse41()) {
+ for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) {
+ kernel_cpu_sse41_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x);
+
+ if(task_pool.canceled())
+ break;
+ }
+ }
+#endif
if(system_cpu_support_sse3()) {
for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) {
kernel_cpu_sse3_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x);
@@ -351,9 +403,9 @@ public:
}
};
-Device *device_cpu_create(DeviceInfo& info, Stats &stats)
+Device *device_cpu_create(DeviceInfo& info, Stats &stats, bool background)
{
- return new CPUDevice(stats);
+ return new CPUDevice(info, stats, background);
}
void device_cpu_info(vector<DeviceInfo>& devices)
diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index 4ce7f6fd729..8db915f769c 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -171,7 +171,8 @@ public:
cuda_assert(cuCtxSetCurrent(NULL));
}
- CUDADevice(DeviceInfo& info, Stats &stats, bool background_) : Device(stats)
+ CUDADevice(DeviceInfo& info, Stats &stats, bool background_)
+ : Device(info, stats, background_)
{
first_error = true;
background = background_;
diff --git a/intern/cycles/device/device_intern.h b/intern/cycles/device/device_intern.h
index d667478beed..7eb66c25a81 100644
--- a/intern/cycles/device/device_intern.h
+++ b/intern/cycles/device/device_intern.h
@@ -21,7 +21,7 @@ CCL_NAMESPACE_BEGIN
class Device;
-Device *device_cpu_create(DeviceInfo& info, Stats &stats);
+Device *device_cpu_create(DeviceInfo& info, Stats &stats, bool background);
Device *device_opencl_create(DeviceInfo& info, Stats &stats, bool background);
Device *device_cuda_create(DeviceInfo& info, Stats &stats, bool background);
Device *device_network_create(DeviceInfo& info, Stats &stats, const char *address);
diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp
index 4df0fdbd4c7..27b9de0769e 100644
--- a/intern/cycles/device/device_multi.cpp
+++ b/intern/cycles/device/device_multi.cpp
@@ -45,25 +45,24 @@ public:
device_ptr unique_ptr;
MultiDevice(DeviceInfo& info, Stats &stats, bool background_)
- : Device(stats), unique_ptr(1)
+ : Device(info, stats, background_), unique_ptr(1)
{
Device *device;
- background = background_;
foreach(DeviceInfo& subinfo, info.multi_devices) {
device = Device::create(subinfo, stats, background);
devices.push_back(SubDevice(device));
}
-#if 0 //def WITH_NETWORK
+#ifdef WITH_NETWORK
/* try to add network devices */
ServerDiscovery discovery(true);
time_sleep(1.0);
- list<string> servers = discovery.get_server_list();
+ vector<string> servers = discovery.get_server_list();
foreach(string& server, servers) {
- device = device_network_create(info, server.c_str());
+ device = device_network_create(info, stats, server.c_str());
if(device)
devices.push_back(SubDevice(device));
}
diff --git a/intern/cycles/device/device_network.cpp b/intern/cycles/device/device_network.cpp
index 23c1a10fa0a..90339b89cce 100644
--- a/intern/cycles/device/device_network.cpp
+++ b/intern/cycles/device/device_network.cpp
@@ -20,9 +20,25 @@
#include "util_foreach.h"
+#if defined(WITH_NETWORK)
+
CCL_NAMESPACE_BEGIN
-#ifdef WITH_NETWORK
+typedef map<device_ptr, device_ptr> PtrMap;
+typedef vector<uint8_t> DataVector;
+typedef map<device_ptr, DataVector> DataMap;
+
+/* tile list */
+typedef vector<RenderTile> TileList;
+
+/* search a list of tiles and find the one that matches the passed render tile */
+static TileList::iterator tile_list_find(TileList& tile_list, RenderTile& tile)
+{
+ for(TileList::iterator it = tile_list.begin(); it != tile_list.end(); ++it)
+ if(tile.x == it->x && tile.y == it->y && tile.start_sample == it->start_sample)
+ return it;
+ return tile_list.end();
+}
class NetworkDevice : public Device
{
@@ -32,8 +48,10 @@ public:
device_ptr mem_counter;
DeviceTask the_task; /* todo: handle multiple tasks */
- NetworkDevice(Stats &stats, const char *address)
- : Device(stats), socket(io_service)
+ thread_mutex rpc_lock;
+
+ NetworkDevice(DeviceInfo& info, Stats &stats, const char *address)
+ : Device(info, stats, true), socket(io_service)
{
stringstream portstr;
portstr << SERVER_PORT;
@@ -64,6 +82,8 @@ public:
void mem_alloc(device_memory& mem, MemoryType type)
{
+ thread_scoped_lock lock(rpc_lock);
+
mem.device_pointer = ++mem_counter;
RPCSend snd(socket, "mem_alloc");
@@ -75,6 +95,8 @@ public:
void mem_copy_to(device_memory& mem)
{
+ thread_scoped_lock lock(rpc_lock);
+
RPCSend snd(socket, "mem_copy_to");
snd.add(mem);
@@ -84,6 +106,10 @@ public:
void mem_copy_from(device_memory& mem, int y, int w, int h, int elem)
{
+ thread_scoped_lock lock(rpc_lock);
+
+ size_t data_size = mem.memory_size();
+
RPCSend snd(socket, "mem_copy_from");
snd.add(mem);
@@ -94,11 +120,13 @@ public:
snd.write();
RPCReceive rcv(socket);
- rcv.read_buffer((void*)mem.data_pointer, mem.memory_size());
+ rcv.read_buffer((void*)mem.data_pointer, data_size);
}
void mem_zero(device_memory& mem)
{
+ thread_scoped_lock lock(rpc_lock);
+
RPCSend snd(socket, "mem_zero");
snd.add(mem);
@@ -108,6 +136,8 @@ public:
void mem_free(device_memory& mem)
{
if(mem.device_pointer) {
+ thread_scoped_lock lock(rpc_lock);
+
RPCSend snd(socket, "mem_free");
snd.add(mem);
@@ -119,6 +149,8 @@ public:
void const_copy_to(const char *name, void *host, size_t size)
{
+ thread_scoped_lock lock(rpc_lock);
+
RPCSend snd(socket, "const_copy_to");
string name_string(name);
@@ -131,6 +163,8 @@ public:
void tex_alloc(const char *name, device_memory& mem, bool interpolation, bool periodic)
{
+ thread_scoped_lock lock(rpc_lock);
+
mem.device_pointer = ++mem_counter;
RPCSend snd(socket, "tex_alloc");
@@ -148,6 +182,8 @@ public:
void tex_free(device_memory& mem)
{
if(mem.device_pointer) {
+ thread_scoped_lock lock(rpc_lock);
+
RPCSend snd(socket, "tex_free");
snd.add(mem);
@@ -157,8 +193,25 @@ public:
}
}
+ bool load_kernels(bool experimental)
+ {
+ thread_scoped_lock lock(rpc_lock);
+
+ RPCSend snd(socket, "load_kernels");
+ snd.add(experimental);
+ snd.write();
+
+ bool result;
+ RPCReceive rcv(socket);
+ rcv.read(result);
+
+ return result;
+ }
+
void task_add(DeviceTask& task)
{
+ thread_scoped_lock lock(rpc_lock);
+
the_task = task;
RPCSend snd(socket, "task_add");
@@ -168,55 +221,73 @@ public:
void task_wait()
{
+ thread_scoped_lock lock(rpc_lock);
+
RPCSend snd(socket, "task_wait");
snd.write();
- list<RenderTile> the_tiles;
+ lock.unlock();
+
+ TileList the_tiles;
/* todo: run this threaded for connecting to multiple clients */
for(;;) {
- RPCReceive rcv(socket);
RenderTile tile;
+ lock.lock();
+ RPCReceive rcv(socket);
+
if(rcv.name == "acquire_tile") {
+ lock.unlock();
+
/* todo: watch out for recursive calls! */
if(the_task.acquire_tile(this, tile)) { /* write return as bool */
the_tiles.push_back(tile);
+ lock.lock();
RPCSend snd(socket, "acquire_tile");
snd.add(tile);
snd.write();
+ lock.unlock();
}
else {
+ lock.lock();
RPCSend snd(socket, "acquire_tile_none");
snd.write();
+ lock.unlock();
}
}
else if(rcv.name == "release_tile") {
rcv.read(tile);
+ lock.unlock();
- for(list<RenderTile>::iterator it = the_tiles.begin(); it != the_tiles.end(); it++) {
- if(tile.x == it->x && tile.y == it->y && tile.start_sample == it->start_sample) {
- tile.buffers = it->buffers;
- the_tiles.erase(it);
- break;
- }
+ TileList::iterator it = tile_list_find(the_tiles, tile);
+ if (it != the_tiles.end()) {
+ tile.buffers = it->buffers;
+ the_tiles.erase(it);
}
assert(tile.buffers != NULL);
the_task.release_tile(tile);
+ lock.lock();
RPCSend snd(socket, "release_tile");
snd.write();
+ lock.unlock();
}
- else if(rcv.name == "task_wait_done")
+ else if(rcv.name == "task_wait_done") {
+ lock.unlock();
break;
+ }
+ else
+ lock.unlock();
}
}
void task_cancel()
{
+ thread_scoped_lock lock(rpc_lock);
RPCSend snd(socket, "task_cancel");
snd.write();
}
@@ -224,7 +295,7 @@ public:
Device *device_network_create(DeviceInfo& info, Stats &stats, const char *address)
{
- return new NetworkDevice(stats, address);
+ return new NetworkDevice(info, stats, address);
}
void device_network_info(vector<DeviceInfo>& devices)
@@ -243,8 +314,10 @@ void device_network_info(vector<DeviceInfo>& devices)
class DeviceServer {
public:
+ thread_mutex rpc_lock;
+
DeviceServer(Device *device_, tcp::socket& socket_)
- : device(device_), socket(socket_)
+ : device(device_), socket(socket_), stop(false), blocked_waiting(false)
{
}
@@ -252,56 +325,151 @@ public:
{
/* receive remote function calls */
for(;;) {
- RPCReceive rcv(socket);
+ listen_step();
- if(rcv.name == "stop")
+ if(stop)
break;
-
- process(rcv);
}
}
protected:
- void process(RPCReceive& rcv)
+ void listen_step()
+ {
+ thread_scoped_lock lock(rpc_lock);
+ RPCReceive rcv(socket);
+
+ if(rcv.name == "stop")
+ stop = true;
+ else
+ process(rcv, lock);
+ }
+
+ /* create a memory buffer for a device buffer and insert it into mem_data */
+ DataVector &data_vector_insert(device_ptr client_pointer, size_t data_size)
+ {
+ /* create a new DataVector and insert it into mem_data */
+ pair<DataMap::iterator,bool> data_ins = mem_data.insert(
+ DataMap::value_type(client_pointer, DataVector()));
+
+ /* make sure it was a unique insertion */
+ assert(data_ins.second);
+
+ /* get a reference to the inserted vector */
+ DataVector &data_v = data_ins.first->second;
+
+ /* size the vector */
+ data_v.resize(data_size);
+
+ return data_v;
+ }
+
+ DataVector &data_vector_find(device_ptr client_pointer)
{
- // fprintf(stderr, "receive process %s\n", rcv.name.c_str());
+ DataMap::iterator i = mem_data.find(client_pointer);
+ assert(i != mem_data.end());
+ return i->second;
+ }
+
+ /* setup mapping and reverse mapping of client_pointer<->real_pointer */
+ void pointer_mapping_insert(device_ptr client_pointer, device_ptr real_pointer)
+ {
+ pair<PtrMap::iterator,bool> mapins;
+
+ /* insert mapping from client pointer to our real device pointer */
+ mapins = ptr_map.insert(PtrMap::value_type(client_pointer, real_pointer));
+ assert(mapins.second);
+
+ /* insert reverse mapping from real our device pointer to client pointer */
+ mapins = ptr_imap.insert(PtrMap::value_type(real_pointer, client_pointer));
+ assert(mapins.second);
+ }
+
+ device_ptr device_ptr_from_client_pointer(device_ptr client_pointer)
+ {
+ PtrMap::iterator i = ptr_map.find(client_pointer);
+ assert(i != ptr_map.end());
+ return i->second;
+ }
+
+ device_ptr device_ptr_from_client_pointer_erase(device_ptr client_pointer)
+ {
+ PtrMap::iterator i = ptr_map.find(client_pointer);
+ assert(i != ptr_map.end());
+
+ device_ptr result = i->second;
+ /* erase the mapping */
+ ptr_map.erase(i);
+
+ /* erase the reverse mapping */
+ PtrMap::iterator irev = ptr_imap.find(result);
+ assert(irev != ptr_imap.end());
+ ptr_imap.erase(irev);
+
+ /* erase the data vector */
+ DataMap::iterator idata = mem_data.find(client_pointer);
+ assert(idata != mem_data.end());
+ mem_data.erase(idata);
+
+ return result;
+ }
+
+ /* note that the lock must be already acquired upon entry.
+ * This is necessary because the caller often peeks at
+ * the header and delegates control to here when it doesn't
+ * specifically handle the current RPC.
+ * The lock must be unlocked before returning */
+ void process(RPCReceive& rcv, thread_scoped_lock &lock)
+ {
if(rcv.name == "mem_alloc") {
MemoryType type;
network_device_memory mem;
- device_ptr remote_pointer;
+ device_ptr client_pointer;
rcv.read(mem);
rcv.read(type);
- /* todo: CPU needs mem.data_pointer */
+ lock.unlock();
+
+ client_pointer = mem.device_pointer;
- remote_pointer = mem.device_pointer;
+ /* create a memory buffer for the device buffer */
+ size_t data_size = mem.memory_size();
+ DataVector &data_v = data_vector_insert(client_pointer, data_size);
- mem_data[remote_pointer] = vector<uint8_t>();
- mem_data[remote_pointer].resize(mem.memory_size());
- if(mem.memory_size())
- mem.data_pointer = (device_ptr)&(mem_data[remote_pointer][0]);
+ if(data_size)
+ mem.data_pointer = (device_ptr)&(data_v[0]);
else
mem.data_pointer = 0;
+ /* perform the allocation on the actual device */
device->mem_alloc(mem, type);
- ptr_map[remote_pointer] = mem.device_pointer;
- ptr_imap[mem.device_pointer] = remote_pointer;
+ /* store a mapping to/from client_pointer and real device pointer */
+ pointer_mapping_insert(client_pointer, mem.device_pointer);
}
else if(rcv.name == "mem_copy_to") {
network_device_memory mem;
rcv.read(mem);
+ lock.unlock();
- device_ptr remote_pointer = mem.device_pointer;
- mem.data_pointer = (device_ptr)&(mem_data[remote_pointer][0]);
+ device_ptr client_pointer = mem.device_pointer;
- rcv.read_buffer((uint8_t*)mem.data_pointer, mem.memory_size());
+ DataVector &data_v = data_vector_find(client_pointer);
- mem.device_pointer = ptr_map[remote_pointer];
+ size_t data_size = mem.memory_size();
+ /* get pointer to memory buffer for device buffer */
+ mem.data_pointer = (device_ptr)&data_v[0];
+
+ /* copy data from network into memory buffer */
+ rcv.read_buffer((uint8_t*)mem.data_pointer, data_size);
+
+ /* translate the client pointer to a real device pointer */
+ mem.device_pointer = device_ptr_from_client_pointer(client_pointer);
+
+ /* copy the data from the memory buffer to the device buffer */
device->mem_copy_to(mem);
}
else if(rcv.name == "mem_copy_from") {
@@ -314,37 +482,47 @@ protected:
rcv.read(h);
rcv.read(elem);
- device_ptr remote_pointer = mem.device_pointer;
- mem.device_pointer = ptr_map[remote_pointer];
- mem.data_pointer = (device_ptr)&(mem_data[remote_pointer][0]);
+ device_ptr client_pointer = mem.device_pointer;
+ mem.device_pointer = device_ptr_from_client_pointer(client_pointer);
+
+ DataVector &data_v = data_vector_find(client_pointer);
+
+ mem.data_pointer = (device_ptr)&(data_v[0]);
device->mem_copy_from(mem, y, w, h, elem);
+ size_t data_size = mem.memory_size();
+
RPCSend snd(socket);
snd.write();
- snd.write_buffer((uint8_t*)mem.data_pointer, mem.memory_size());
+ snd.write_buffer((uint8_t*)mem.data_pointer, data_size);
+ lock.unlock();
}
else if(rcv.name == "mem_zero") {
network_device_memory mem;
rcv.read(mem);
- device_ptr remote_pointer = mem.device_pointer;
- mem.device_pointer = ptr_map[mem.device_pointer];
- mem.data_pointer = (device_ptr)&(mem_data[remote_pointer][0]);
+ lock.unlock();
+
+ device_ptr client_pointer = mem.device_pointer;
+ mem.device_pointer = device_ptr_from_client_pointer(client_pointer);
+
+ DataVector &data_v = data_vector_find(client_pointer);
+
+ mem.data_pointer = (device_ptr)&(data_v[0]);
device->mem_zero(mem);
}
else if(rcv.name == "mem_free") {
network_device_memory mem;
- device_ptr remote_pointer;
+ device_ptr client_pointer;
rcv.read(mem);
+ lock.unlock();
+
+ client_pointer = mem.device_pointer;
- remote_pointer = mem.device_pointer;
- mem.device_pointer = ptr_map[mem.device_pointer];
- ptr_map.erase(remote_pointer);
- ptr_imap.erase(mem.device_pointer);
- mem_data.erase(remote_pointer);
+ mem.device_pointer = device_ptr_from_client_pointer_erase(client_pointer);
device->mem_free(mem);
}
@@ -357,6 +535,7 @@ protected:
vector<char> host_vector(size);
rcv.read_buffer(&host_vector[0], size);
+ lock.unlock();
device->const_copy_to(name_string.c_str(), &host_vector[0], size);
}
@@ -365,53 +544,76 @@ protected:
string name;
bool interpolation;
bool periodic;
- device_ptr remote_pointer;
+ device_ptr client_pointer;
rcv.read(name);
rcv.read(mem);
rcv.read(interpolation);
rcv.read(periodic);
+ lock.unlock();
+
+ client_pointer = mem.device_pointer;
+
+ size_t data_size = mem.memory_size();
- remote_pointer = mem.device_pointer;
+ DataVector &data_v = data_vector_insert(client_pointer, data_size);
- mem_data[remote_pointer] = vector<uint8_t>();
- mem_data[remote_pointer].resize(mem.memory_size());
- if(mem.memory_size())
- mem.data_pointer = (device_ptr)&(mem_data[remote_pointer][0]);
+ if(data_size)
+ mem.data_pointer = (device_ptr)&(data_v[0]);
else
mem.data_pointer = 0;
- rcv.read_buffer((uint8_t*)mem.data_pointer, mem.memory_size());
+ rcv.read_buffer((uint8_t*)mem.data_pointer, data_size);
device->tex_alloc(name.c_str(), mem, interpolation, periodic);
- ptr_map[remote_pointer] = mem.device_pointer;
- ptr_imap[mem.device_pointer] = remote_pointer;
+ pointer_mapping_insert(client_pointer, mem.device_pointer);
}
else if(rcv.name == "tex_free") {
network_device_memory mem;
- device_ptr remote_pointer;
+ device_ptr client_pointer;
rcv.read(mem);
+ lock.unlock();
- remote_pointer = mem.device_pointer;
- mem.device_pointer = ptr_map[mem.device_pointer];
- ptr_map.erase(remote_pointer);
- ptr_map.erase(mem.device_pointer);
- mem_data.erase(remote_pointer);
+ client_pointer = mem.device_pointer;
+
+ mem.device_pointer = device_ptr_from_client_pointer_erase(client_pointer);
device->tex_free(mem);
}
+ else if(rcv.name == "load_kernels") {
+ bool experimental;
+ rcv.read(experimental);
+
+ bool result;
+ result = device->load_kernels(experimental);
+ RPCSend snd(socket);
+ snd.add(result);
+ snd.write();
+ lock.unlock();
+ }
else if(rcv.name == "task_add") {
DeviceTask task;
rcv.read(task);
+ lock.unlock();
+
+ if(task.buffer)
+ task.buffer = device_ptr_from_client_pointer(task.buffer);
+
+ if(task.rgba_half)
+ task.rgba_half = device_ptr_from_client_pointer(task.rgba_half);
+
+ if(task.rgba_byte)
+ task.rgba_byte = device_ptr_from_client_pointer(task.rgba_byte);
+
+ if(task.shader_input)
+ task.shader_input = device_ptr_from_client_pointer(task.shader_input);
+
+ if(task.shader_output)
+ task.shader_output = device_ptr_from_client_pointer(task.shader_output);
- if(task.buffer) task.buffer = ptr_map[task.buffer];
- if(task.rgba_byte) task.rgba_byte = ptr_map[task.rgba_byte];
- if(task.rgba_half) task.rgba_half = ptr_map[task.rgba_half];
- if(task.shader_input) task.shader_input = ptr_map[task.shader_input];
- if(task.shader_output) task.shader_output = ptr_map[task.shader_output];
task.acquire_tile = function_bind(&DeviceServer::task_acquire_tile, this, _1, _2);
task.release_tile = function_bind(&DeviceServer::task_release_tile, this, _1);
@@ -422,14 +624,44 @@ protected:
device->task_add(task);
}
else if(rcv.name == "task_wait") {
+ lock.unlock();
+
+ blocked_waiting = true;
device->task_wait();
+ blocked_waiting = false;
+ lock.lock();
RPCSend snd(socket, "task_wait_done");
snd.write();
+ lock.unlock();
}
else if(rcv.name == "task_cancel") {
+ lock.unlock();
device->task_cancel();
}
+ else if(rcv.name == "acquire_tile") {
+ AcquireEntry entry;
+ entry.name = rcv.name;
+ rcv.read(entry.tile);
+ acquire_queue.push_back(entry);
+ lock.unlock();
+ }
+ else if(rcv.name == "acquire_tile_none") {
+ AcquireEntry entry;
+ entry.name = rcv.name;
+ acquire_queue.push_back(entry);
+ lock.unlock();
+ }
+ else if(rcv.name == "release_tile") {
+ AcquireEntry entry;
+ entry.name = rcv.name;
+ acquire_queue.push_back(entry);
+ lock.unlock();
+ }
+ else {
+ cout << "Error: unexpected RPC receive call \"" + rcv.name + "\"\n";
+ lock.unlock();
+ }
}
bool task_acquire_tile(Device *device, RenderTile& tile)
@@ -441,23 +673,34 @@ protected:
RPCSend snd(socket, "acquire_tile");
snd.write();
- while(1) {
- RPCReceive rcv(socket);
+ do {
+ if(blocked_waiting)
+ listen_step();
- if(rcv.name == "acquire_tile") {
- rcv.read(tile);
+ /* todo: avoid busy wait loop */
+ thread_scoped_lock lock(rpc_lock);
- if(tile.buffer) tile.buffer = ptr_map[tile.buffer];
- if(tile.rng_state) tile.rng_state = ptr_map[tile.rng_state];
+ if(!acquire_queue.empty()) {
+ AcquireEntry entry = acquire_queue.front();
+ acquire_queue.pop_front();
- result = true;
- break;
+ if(entry.name == "acquire_tile") {
+ tile = entry.tile;
+
+ if(tile.buffer) tile.buffer = ptr_map[tile.buffer];
+ if(tile.rng_state) tile.rng_state = ptr_map[tile.rng_state];
+
+ result = true;
+ break;
+ }
+ else if(entry.name == "acquire_tile_none") {
+ break;
+ }
+ else {
+ cout << "Error: unexpected acquire RPC receive call \"" + entry.name + "\"\n";
+ }
}
- else if(rcv.name == "acquire_tile_none")
- break;
- else
- process(rcv);
- }
+ } while(acquire_queue.empty() && !stop);
return result;
}
@@ -479,18 +722,34 @@ protected:
if(tile.buffer) tile.buffer = ptr_imap[tile.buffer];
if(tile.rng_state) tile.rng_state = ptr_imap[tile.rng_state];
- RPCSend snd(socket, "release_tile");
- snd.add(tile);
- snd.write();
+ {
+ thread_scoped_lock lock(rpc_lock);
+ RPCSend snd(socket, "release_tile");
+ snd.add(tile);
+ snd.write();
+ lock.unlock();
+ }
- while(1) {
- RPCReceive rcv(socket);
+ do {
+ if(blocked_waiting)
+ listen_step();
- if(rcv.name == "release_tile")
- break;
- else
- process(rcv);
- }
+ /* todo: avoid busy wait loop */
+ thread_scoped_lock lock(rpc_lock);
+
+ if(!acquire_queue.empty()) {
+ AcquireEntry entry = acquire_queue.front();
+ acquire_queue.pop_front();
+
+ if(entry.name == "release_tile") {
+ lock.unlock();
+ break;
+ }
+ else {
+ cout << "Error: unexpected release RPC receive call \"" + entry.name + "\"\n";
+ }
+ }
+ } while(acquire_queue.empty() && !stop);
}
bool task_get_cancel()
@@ -503,11 +762,20 @@ protected:
tcp::socket& socket;
/* mapping of remote to local pointer */
- map<device_ptr, device_ptr> ptr_map;
- map<device_ptr, device_ptr> ptr_imap;
- map<device_ptr, vector<uint8_t> > mem_data;
+ PtrMap ptr_map;
+ PtrMap ptr_imap;
+ DataMap mem_data;
+
+ struct AcquireEntry {
+ string name;
+ RenderTile tile;
+ };
thread_mutex acquire_mutex;
+ list<AcquireEntry> acquire_queue;
+
+ bool stop;
+ bool blocked_waiting;
/* todo: free memory and device (osl) on network error */
};
@@ -540,7 +808,8 @@ void Device::server_run()
}
}
+CCL_NAMESPACE_END
+
#endif
-CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_network.h b/intern/cycles/device/device_network.h
index db399cf4240..d639450b9ea 100644
--- a/intern/cycles/device/device_network.h
+++ b/intern/cycles/device/device_network.h
@@ -28,6 +28,8 @@
#include <boost/thread.hpp>
#include <iostream>
+#include <sstream>
+#include <deque>
#include "buffers.h"
@@ -70,12 +72,12 @@ public:
: name(name_), socket(socket_), archive(archive_stream), sent(false)
{
archive & name_;
+
+ fprintf(stderr, "rpc send %s\n", name.c_str());
}
~RPCSend()
{
- if(!sent)
- fprintf(stderr, "Error: RPC %s not sent\n", name.c_str());
}
void add(const device_memory& mem)
@@ -98,13 +100,14 @@ public:
archive & task.offset & task.stride;
archive & task.shader_input & task.shader_output & task.shader_eval_type;
archive & task.shader_x & task.shader_w;
+ archive & task.need_finish_queue;
}
void add(const RenderTile& tile)
{
archive & tile.x & tile.y & tile.w & tile.h;
archive & tile.start_sample & tile.num_samples & tile.sample;
- archive & tile.offset & tile.stride;
+ archive & tile.resolution & tile.offset & tile.stride;
archive & tile.buffer & tile.rng_state;
}
@@ -178,6 +181,7 @@ public:
size_t data_size;
if((header_stream >> hex >> data_size)) {
+
vector<char> data(data_size);
size_t len = boost::asio::read(socket, boost::asio::buffer(data));
@@ -191,15 +195,19 @@ public:
archive = new boost::archive::text_iarchive(*archive_stream);
*archive & name;
+ fprintf(stderr, "rpc receive %s\n", name.c_str());
+ }
+ else {
+ cout << "Network receive error: data size doesn't match header\n";
}
- else
- cout << "Network receive error: data size doens't match header\n";
}
- else
+ else {
cout << "Network receive error: can't decode data size from header\n";
+ }
}
- else
+ else {
cout << "Network receive error: invalid header size\n";
+ }
}
~RPCReceive()
@@ -235,9 +243,10 @@ public:
*archive & type & task.x & task.y & task.w & task.h;
*archive & task.rgba_byte & task.rgba_half & task.buffer & task.sample & task.num_samples;
- *archive & task.resolution & task.offset & task.stride;
+ *archive & task.offset & task.stride;
*archive & task.shader_input & task.shader_output & task.shader_eval_type;
*archive & task.shader_x & task.shader_w;
+ *archive & task.need_finish_queue;
task.type = (DeviceTask::Type)type;
}
@@ -247,7 +256,7 @@ public:
*archive & tile.x & tile.y & tile.w & tile.h;
*archive & tile.start_sample & tile.num_samples & tile.sample;
*archive & tile.resolution & tile.offset & tile.stride;
- *archive & tile.buffer & tile.rng_state & tile.rgba_byte & tile.rgba_half;
+ *archive & tile.buffer & tile.rng_state;
tile.buffers = NULL;
}
@@ -303,12 +312,12 @@ public:
delete work;
}
- list<string> get_server_list()
+ vector<string> get_server_list()
{
- list<string> result;
+ vector<string> result;
mutex.lock();
- result = servers;
+ result = vector<string>(servers.begin(), servers.end());
mutex.unlock();
return result;
@@ -333,11 +342,8 @@ private:
mutex.lock();
/* add address if it's not already in the list */
- bool found = false;
-
- foreach(string& server, servers)
- if(server == address)
- found = true;
+ bool found = std::find(servers.begin(), servers.end(),
+ address) != servers.end();
if(!found)
servers.push_back(address);
@@ -393,10 +399,21 @@ private:
/* buffer and endpoint for receiving messages */
char receive_buffer[256];
boost::asio::ip::udp::endpoint receive_endpoint;
+
+ // os, version, devices, status, host name, group name, ip as far as fields go
+ struct ServerInfo {
+ string cycles_version;
+ string os;
+ int device_count;
+ string status;
+ string host_name;
+ string group_name;
+ string host_addr;
+ };
/* collection of server addresses in list */
bool collect_servers;
- list<string> servers;
+ vector<string> servers;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp
index 11c7bc6f099..98d3b07b7ee 100644
--- a/intern/cycles/device/device_opencl.cpp
+++ b/intern/cycles/device/device_opencl.cpp
@@ -423,9 +423,8 @@ public:
}
OpenCLDevice(DeviceInfo& info, Stats &stats, bool background_)
- : Device(stats)
+ : Device(info, stats, background_)
{
- background = background_;
cpPlatform = NULL;
cdDevice = NULL;
cxContext = NULL;
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 56ba0e08743..39444b91131 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -190,13 +190,18 @@ endif()
include_directories(${INC})
include_directories(SYSTEM ${INC_SYS})
-add_library(cycles_kernel ${SRC} ${SRC_HEADERS} ${SRC_CLOSURE_HEADERS} ${SRC_SVM_HEADERS})
-
if(WITH_CYCLES_OPTIMIZED_KERNEL)
set_source_files_properties(kernel_sse2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE2_KERNEL_FLAGS}")
set_source_files_properties(kernel_sse3.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE3_KERNEL_FLAGS}")
endif()
+if(WITH_CYCLES_OPTIMIZED_KERNEL_SSE41)
+ set_source_files_properties(kernel_sse41.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE41_KERNEL_FLAGS}")
+ list(APPEND SRC kernel_sse41.cpp)
+endif()
+
+add_library(cycles_kernel ${SRC} ${SRC_HEADERS} ${SRC_CLOSURE_HEADERS} ${SRC_SVM_HEADERS})
+
if(WITH_CYCLES_CUDA)
add_dependencies(cycles_kernel cycles_kernel_cuda)
endif()
diff --git a/intern/cycles/kernel/closure/volume.h b/intern/cycles/kernel/closure/volume.h
index f30b30c8c76..f4932568c1f 100644
--- a/intern/cycles/kernel/closure/volume.h
+++ b/intern/cycles/kernel/closure/volume.h
@@ -53,11 +53,6 @@ ccl_device float3 volume_transparent_eval_phase(const ShaderClosure *sc, const f
ccl_device float3 volume_eval_phase(KernelGlobals *kg, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
{
-#ifdef __OSL__
- if(kg->osl && sc->prim)
- return OSLShader::volume_eval_phase(sc, omega_in, omega_out);
-#endif
-
float3 eval;
switch(sc->type) {
diff --git a/intern/cycles/kernel/kernel.h b/intern/cycles/kernel/kernel.h
index 361f5b0856d..105a3887da0 100644
--- a/intern/cycles/kernel/kernel.h
+++ b/intern/cycles/kernel/kernel.h
@@ -61,6 +61,15 @@ void kernel_cpu_sse3_convert_to_half_float(KernelGlobals *kg, uchar4 *rgba, floa
float sample_scale, int x, int y, int offset, int stride);
void kernel_cpu_sse3_shader(KernelGlobals *kg, uint4 *input, float4 *output,
int type, int i);
+
+void kernel_cpu_sse41_path_trace(KernelGlobals *kg, float *buffer, unsigned int *rng_state,
+ int sample, int x, int y, int offset, int stride);
+void kernel_cpu_sse41_convert_to_byte(KernelGlobals *kg, uchar4 *rgba, float *buffer,
+ float sample_scale, int x, int y, int offset, int stride);
+void kernel_cpu_sse41_convert_to_half_float(KernelGlobals *kg, uchar4 *rgba, float *buffer,
+ float sample_scale, int x, int y, int offset, int stride);
+void kernel_cpu_sse41_shader(KernelGlobals *kg, uint4 *input, float4 *output,
+ int type, int i);
#endif
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_primitive.h b/intern/cycles/kernel/kernel_primitive.h
index ababad28f35..0e39c489fbc 100644
--- a/intern/cycles/kernel/kernel_primitive.h
+++ b/intern/cycles/kernel/kernel_primitive.h
@@ -89,6 +89,25 @@ ccl_device float3 primitive_uv(KernelGlobals *kg, ShaderData *sd)
return uv;
}
+ccl_device bool primitive_ptex(KernelGlobals *kg, ShaderData *sd, float2 *uv, int *face_id)
+{
+ /* storing ptex data as attributes is not memory efficient but simple for tests */
+ AttributeElement elem_face_id, elem_uv;
+ int offset_face_id = find_attribute(kg, sd, ATTR_STD_PTEX_FACE_ID, &elem_face_id);
+ int offset_uv = find_attribute(kg, sd, ATTR_STD_PTEX_UV, &elem_uv);
+
+ if(offset_face_id == ATTR_STD_NOT_FOUND || offset_uv == ATTR_STD_NOT_FOUND)
+ return false;
+
+ float3 uv3 = primitive_attribute_float3(kg, sd, elem_uv, offset_uv, NULL, NULL);
+ float face_id_f = primitive_attribute_float(kg, sd, elem_face_id, offset_face_id, NULL, NULL);
+
+ *uv = make_float2(uv3.x, uv3.y);
+ *face_id = (int)face_id_f;
+
+ return true;
+}
+
ccl_device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd)
{
#ifdef __HAIR__
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index 77154ce3aef..dbc705ea791 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -764,11 +764,6 @@ ccl_device float3 shader_bssrdf_sum(ShaderData *sd, float3 *N_, float *texture_b
ccl_device float3 emissive_eval(KernelGlobals *kg, ShaderData *sd, ShaderClosure *sc)
{
-#ifdef __OSL__
- if(kg->osl && sc->prim)
- return OSLShader::emissive_eval(sd, sc);
-#endif
-
return emissive_simple_eval(sd->Ng, sd->I);
}
diff --git a/intern/cycles/kernel/kernel_sse41.cpp b/intern/cycles/kernel/kernel_sse41.cpp
new file mode 100644
index 00000000000..0c68fd3651b
--- /dev/null
+++ b/intern/cycles/kernel/kernel_sse41.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2011-2013 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+/* Optimized CPU kernel entry points. This file is compiled with SSE3/SSSE3
+ * optimization flags and nearly all functions inlined, while kernel.cpp
+ * is compiled without for other CPU's. */
+
+#ifdef WITH_OPTIMIZED_KERNEL
+
+/* SSE optimization disabled for now on 32 bit, see bug #36316 */
+#if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86)))
+#define __KERNEL_SSE2__
+#define __KERNEL_SSE3__
+#define __KERNEL_SSSE3__
+#define __KERNEL_SSE41__
+#endif
+
+#include "kernel.h"
+#include "kernel_compat_cpu.h"
+#include "kernel_math.h"
+#include "kernel_types.h"
+#include "kernel_globals.h"
+#include "kernel_film.h"
+#include "kernel_path.h"
+#include "kernel_displace.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* Path Tracing */
+
+void kernel_cpu_sse41_path_trace(KernelGlobals *kg, float *buffer, unsigned int *rng_state, int sample, int x, int y, int offset, int stride)
+{
+#ifdef __BRANCHED_PATH__
+ if(kernel_data.integrator.branched)
+ kernel_branched_path_trace(kg, buffer, rng_state, sample, x, y, offset, stride);
+ else
+#endif
+ kernel_path_trace(kg, buffer, rng_state, sample, x, y, offset, stride);
+}
+
+/* Film */
+
+void kernel_cpu_sse41_convert_to_byte(KernelGlobals *kg, uchar4 *rgba, float *buffer, float sample_scale, int x, int y, int offset, int stride)
+{
+ kernel_film_convert_to_byte(kg, rgba, buffer, sample_scale, x, y, offset, stride);
+}
+
+void kernel_cpu_sse41_convert_to_half_float(KernelGlobals *kg, uchar4 *rgba, float *buffer, float sample_scale, int x, int y, int offset, int stride)
+{
+ kernel_film_convert_to_half_float(kg, rgba, buffer, sample_scale, x, y, offset, stride);
+}
+
+/* Shader Evaluate */
+
+void kernel_cpu_sse41_shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int i)
+{
+ kernel_shader_evaluate(kg, input, output, (ShaderEvalType)type, i);
+}
+
+CCL_NAMESPACE_END
+
+#endif
+
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 3371c580c71..51a49348810 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -436,6 +436,8 @@ typedef enum AttributeStandard {
ATTR_STD_MOTION_POST,
ATTR_STD_PARTICLE,
ATTR_STD_CURVE_INTERCEPT,
+ ATTR_STD_PTEX_FACE_ID,
+ ATTR_STD_PTEX_UV,
ATTR_STD_NUM,
ATTR_STD_NOT_FOUND = ~0
diff --git a/intern/cycles/kernel/osl/background.cpp b/intern/cycles/kernel/osl/background.cpp
index eed4446cddc..2facced0914 100644
--- a/intern/cycles/kernel/osl/background.cpp
+++ b/intern/cycles/kernel/osl/background.cpp
@@ -46,14 +46,9 @@ using namespace OSL;
/// to return a color in background shaders. No methods,
/// only the weight is taking into account
///
-class GenericBackgroundClosure : public OSL::BackgroundClosure {
+class GenericBackgroundClosure : public CClosurePrimitive {
public:
- GenericBackgroundClosure() {}
-
- void setup() {};
- size_t memsize() const { return sizeof(*this); }
- const char *name() const { return "background"; }
- void print_on(std::ostream &out) const { out << name() << " ()"; }
+ GenericBackgroundClosure() : CClosurePrimitive(Background) {}
};
/// Holdout closure
@@ -63,14 +58,9 @@ public:
/// point. No parameters, only the weight will be
/// used
///
-class HoldoutClosure : ClosurePrimitive {
+class HoldoutClosure : CClosurePrimitive {
public:
- HoldoutClosure () : ClosurePrimitive(Holdout) {}
-
- void setup() {};
- size_t memsize() const { return sizeof(*this); }
- const char *name() const { return "holdout"; }
- void print_on(std::ostream &out) const { out << name() << " ()"; }
+ HoldoutClosure () : CClosurePrimitive(Holdout) {}
};
/// ambient occlusion closure
@@ -79,14 +69,9 @@ public:
/// to return a color in ambient occlusion shaders. No methods,
/// only the weight is taking into account
///
-class AmbientOcclusionClosure : public ClosurePrimitive {
+class AmbientOcclusionClosure : public CClosurePrimitive {
public:
- AmbientOcclusionClosure () : ClosurePrimitive((ClosurePrimitive::Category)AmbientOcclusion) {}
-
- void setup() {};
- size_t memsize() const { return sizeof(*this); }
- const char *name() const { return "ambient_occlusion"; }
- void print_on(std::ostream &out) const { out << name() << " ()"; }
+ AmbientOcclusionClosure () : CClosurePrimitive(AmbientOcclusion) {}
};
ClosureParam *closure_background_params()
@@ -98,7 +83,7 @@ ClosureParam *closure_background_params()
return params;
}
-CLOSURE_PREPARE(closure_background_prepare, GenericBackgroundClosure)
+CCLOSURE_PREPARE(closure_background_prepare, GenericBackgroundClosure)
ClosureParam *closure_holdout_params()
{
@@ -108,7 +93,7 @@ ClosureParam *closure_holdout_params()
return params;
}
-CLOSURE_PREPARE(closure_holdout_prepare, HoldoutClosure)
+CCLOSURE_PREPARE(closure_holdout_prepare, HoldoutClosure)
ClosureParam *closure_ambient_occlusion_params()
{
@@ -119,7 +104,7 @@ ClosureParam *closure_ambient_occlusion_params()
return params;
}
-CLOSURE_PREPARE(closure_ambient_occlusion_prepare, AmbientOcclusionClosure)
+CCLOSURE_PREPARE(closure_ambient_occlusion_prepare, AmbientOcclusionClosure)
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
index a320bea118a..8f9c2efd470 100644
--- a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
+++ b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
@@ -46,12 +46,11 @@ using namespace OSL;
class DiffuseRampClosure : public CBSDFClosure {
public:
- DiffuseRampClosure() : CBSDFClosure(LABEL_DIFFUSE) {}
Color3 colors[8];
float3 fcolors[8];
- size_t memsize() const { return sizeof(*this); }
- const char *name() const { return "diffuse_ramp"; }
+ DiffuseRampClosure() : CBSDFClosure(LABEL_DIFFUSE)
+ {}
void setup()
{
@@ -62,21 +61,11 @@ public:
fcolors[i] = TO_FLOAT3(colors[i]);
}
- bool mergeable(const ClosurePrimitive *other) const
- {
- return false;
- }
-
void blur(float roughness)
{
bsdf_diffuse_ramp_blur(&sc, roughness);
}
- void print_on(std::ostream &out) const
- {
- out << name() << " ((" << sc.N[0] << ", " << sc.N[1] << ", " << sc.N[2] << "))";
- }
-
float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const
{
return bsdf_diffuse_ramp_eval_reflect(&sc, fcolors, omega_out, omega_in, &pdf);
@@ -109,7 +98,7 @@ ClosureParam *closure_bsdf_diffuse_ramp_params()
return params;
}
-CLOSURE_PREPARE(closure_bsdf_diffuse_ramp_prepare, DiffuseRampClosure)
+CCLOSURE_PREPARE(closure_bsdf_diffuse_ramp_prepare, DiffuseRampClosure)
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
index ef656ee7d5f..c5851747b54 100644
--- a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
+++ b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
@@ -45,12 +45,11 @@ using namespace OSL;
class PhongRampClosure : public CBSDFClosure {
public:
- PhongRampClosure() : CBSDFClosure(LABEL_GLOSSY) {}
Color3 colors[8];
float3 fcolors[8];
- size_t memsize() const { return sizeof(*this); }
- const char *name() const { return "phong_ramp"; }
+ PhongRampClosure() : CBSDFClosure(LABEL_GLOSSY)
+ {}
void setup()
{
@@ -61,21 +60,11 @@ public:
fcolors[i] = TO_FLOAT3(colors[i]);
}
- bool mergeable(const ClosurePrimitive *other) const
- {
- return false;
- }
-
void blur(float roughness)
{
bsdf_phong_ramp_blur(&sc, roughness);
}
- void print_on(std::ostream &out) const
- {
- out << name() << " ((" << sc.N[0] << ", " << sc.N[1] << ", " << sc.N[2] << "))";
- }
-
float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const
{
return bsdf_phong_ramp_eval_reflect(&sc, fcolors, omega_out, omega_in, &pdf);
@@ -109,7 +98,7 @@ ClosureParam *closure_bsdf_phong_ramp_params()
return params;
}
-CLOSURE_PREPARE(closure_bsdf_phong_ramp_prepare, PhongRampClosure)
+CCLOSURE_PREPARE(closure_bsdf_phong_ramp_prepare, PhongRampClosure)
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/emissive.cpp b/intern/cycles/kernel/osl/emissive.cpp
index 7d9fa81dbdd..02935542c56 100644
--- a/intern/cycles/kernel/osl/emissive.cpp
+++ b/intern/cycles/kernel/osl/emissive.cpp
@@ -50,18 +50,9 @@ using namespace OSL;
/// outer_angle limit. It can also behave as a lambertian emitter
/// if the provided angles are PI/2, which is the default
///
-class GenericEmissiveClosure : public EmissiveClosure {
+class GenericEmissiveClosure : public CClosurePrimitive {
public:
- GenericEmissiveClosure() { }
-
- void setup() {}
- size_t memsize() const { return sizeof(*this); }
- const char *name() const { return "emission"; }
-
- void print_on(std::ostream &out) const
- {
- out << name() << "()";
- }
+ GenericEmissiveClosure() : CClosurePrimitive(Emissive) { }
Color3 eval(const Vec3 &Ng, const Vec3 &omega_out) const
{
@@ -92,7 +83,7 @@ ClosureParam *closure_emission_params()
return params;
}
-CLOSURE_PREPARE(closure_emission_prepare, GenericEmissiveClosure)
+CCLOSURE_PREPARE(closure_emission_prepare, GenericEmissiveClosure)
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/osl_bssrdf.cpp b/intern/cycles/kernel/osl/osl_bssrdf.cpp
index 975967c0bbb..94337290d20 100644
--- a/intern/cycles/kernel/osl/osl_bssrdf.cpp
+++ b/intern/cycles/kernel/osl/osl_bssrdf.cpp
@@ -51,24 +51,14 @@ using namespace OSL;
class CubicBSSRDFClosure : public CBSSRDFClosure {
public:
- size_t memsize() const { return sizeof(*this); }
- const char *name() const { return "bssrdf_cubic"; }
+ CubicBSSRDFClosure()
+ {}
void setup()
{
sc.type = CLOSURE_BSSRDF_CUBIC_ID;
sc.data0 = fabsf(average(radius));
}
-
- bool mergeable(const ClosurePrimitive *other) const
- {
- return false;
- }
-
- void print_on(std::ostream &out) const
- {
- out << name() << " ((" << sc.N[0] << ", " << sc.N[1] << ", " << sc.N[2] << "))";
- }
};
ClosureParam *closure_bssrdf_cubic_params()
@@ -96,30 +86,20 @@ ClosureParam *closure_bssrdf_cubic_extended_params()
return params;
}
-CLOSURE_PREPARE(closure_bssrdf_cubic_prepare, CubicBSSRDFClosure)
+CCLOSURE_PREPARE(closure_bssrdf_cubic_prepare, CubicBSSRDFClosure)
/* Gaussian */
class GaussianBSSRDFClosure : public CBSSRDFClosure {
public:
- size_t memsize() const { return sizeof(*this); }
- const char *name() const { return "bssrdf_gaussian"; }
+ GaussianBSSRDFClosure()
+ {}
void setup()
{
sc.type = CLOSURE_BSSRDF_GAUSSIAN_ID;
sc.data0 = fabsf(average(radius));
}
-
- bool mergeable(const ClosurePrimitive *other) const
- {
- return false;
- }
-
- void print_on(std::ostream &out) const
- {
- out << name() << " ((" << sc.N[0] << ", " << sc.N[1] << ", " << sc.N[2] << "))";
- }
};
ClosureParam *closure_bssrdf_gaussian_params()
@@ -146,7 +126,7 @@ ClosureParam *closure_bssrdf_gaussian_extended_params()
return params;
}
-CLOSURE_PREPARE(closure_bssrdf_gaussian_prepare, GaussianBSSRDFClosure)
+CCLOSURE_PREPARE(closure_bssrdf_gaussian_prepare, GaussianBSSRDFClosure)
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/osl_bssrdf.h b/intern/cycles/kernel/osl/osl_bssrdf.h
index fc1a4c587cc..6aee2c28ea8 100644
--- a/intern/cycles/kernel/osl/osl_bssrdf.h
+++ b/intern/cycles/kernel/osl/osl_bssrdf.h
@@ -37,20 +37,20 @@
#include <OSL/oslexec.h>
#include <OSL/genclosure.h>
+#include "osl_closures.h"
+
#include "kernel_types.h"
#include "util_types.h"
CCL_NAMESPACE_BEGIN
-class CBSSRDFClosure : public OSL::ClosurePrimitive {
+class CBSSRDFClosure : public CClosurePrimitive {
public:
ShaderClosure sc;
float3 radius;
- CBSSRDFClosure() : OSL::ClosurePrimitive(BSSRDF) { memset(&sc, 0, sizeof(sc)); }
- ~CBSSRDFClosure() { }
-
+ CBSSRDFClosure() : CClosurePrimitive(BSSRDF) { }
int scattering() const { return LABEL_DIFFUSE; }
};
diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp
index 221406a1716..340e4492584 100644
--- a/intern/cycles/kernel/osl/osl_closures.cpp
+++ b/intern/cycles/kernel/osl/osl_closures.cpp
@@ -171,25 +171,16 @@ BSDF_CLOSURE_CLASS_END(HairTransmission, hair_transmission)
/* Registration */
-static void generic_closure_setup(OSL::RendererServices *, int id, void *data)
-{
- assert(data);
- OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)data;
- prim->setup();
-}
-
-static bool generic_closure_compare(int id, const void *dataA, const void *dataB)
-{
- assert(dataA && dataB);
-
- OSL::ClosurePrimitive *primA = (OSL::ClosurePrimitive *)dataA;
- OSL::ClosurePrimitive *primB = (OSL::ClosurePrimitive *)dataB;
- return primA->mergeable(primB);
-}
-
static void register_closure(OSL::ShadingSystem *ss, const char *name, int id, OSL::ClosureParam *params, OSL::PrepareClosureFunc prepare)
{
- ss->register_closure(name, id, params, prepare, generic_closure_setup, generic_closure_compare);
+ /* optimization: it's possible to not use a prepare function at all and
+ * only initialize the actual class when accessing the closure component
+ * data, but then we need to map the id to the class somehow */
+#ifdef CLOSURE_PREPARE
+ ss->register_closure(name, id, params, prepare, NULL, NULL);
+#else
+ ss->register_closure(name, id, params, prepare, NULL);
+#endif
}
void OSLShader::register_closures(OSLShadingSystem *ss_)
diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h
index 6632c2c57e5..b6c38e01b23 100644
--- a/intern/cycles/kernel/osl/osl_closures.h
+++ b/intern/cycles/kernel/osl/osl_closures.h
@@ -66,36 +66,52 @@ void closure_westin_sheen_prepare(OSL::RendererServices *, int id, void *data);
void closure_bssrdf_cubic_prepare(OSL::RendererServices *, int id, void *data);
void closure_bssrdf_gaussian_prepare(OSL::RendererServices *, int id, void *data);
-enum {
- AmbientOcclusion = 100
-};
-
-#define CLOSURE_PREPARE(name, classname) \
+#define CCLOSURE_PREPARE(name, classname) \
void name(RendererServices *, int id, void *data) \
{ \
memset(data, 0, sizeof(classname)); \
new (data) classname(); \
}
-#define CLOSURE_PREPARE_STATIC(name, classname) static CLOSURE_PREPARE(name, classname)
+#define CCLOSURE_PREPARE_STATIC(name, classname) static CCLOSURE_PREPARE(name, classname)
#define CLOSURE_FLOAT3_PARAM(st, fld) \
- { TypeDesc::TypeVector, reckless_offsetof(st, fld), NULL, sizeof(OSL::Vec3) }
+ { TypeDesc::TypeVector, reckless_offsetof(st, fld), NULL, sizeof(OSL::Vec3) }
#define TO_VEC3(v) OSL::Vec3(v.x, v.y, v.z)
#define TO_COLOR3(v) OSL::Color3(v.x, v.y, v.z)
#define TO_FLOAT3(v) make_float3(v[0], v[1], v[2])
+/* Closure */
+
+class CClosurePrimitive {
+public:
+ enum Category {
+ BSDF, ///< Reflective and/or transmissive surface
+ BSSRDF, ///< Sub-surface light transfer
+ Emissive, ///< Light emission
+ Background, ///< Background emission
+ Volume, ///< Volume scattering
+ Holdout, ///< Holdout from alpha
+ AmbientOcclusion, ///< Ambient occlusion
+ };
+
+ CClosurePrimitive (Category category_) : category (category_) {}
+ virtual ~CClosurePrimitive() {}
+ virtual void setup() {}
+
+ Category category;
+};
+
/* BSDF */
-class CBSDFClosure : public OSL::ClosurePrimitive {
+class CBSDFClosure : public CClosurePrimitive {
public:
ShaderClosure sc;
- CBSDFClosure(int scattering) : OSL::ClosurePrimitive(BSDF),
+ CBSDFClosure(int scattering) : CClosurePrimitive(BSDF),
m_scattering_label(scattering), m_shaderdata_flag(0)
- { memset(&sc, 0, sizeof(sc)); }
- ~CBSDFClosure() { }
+ {}
int scattering() const { return m_scattering_label; }
int shaderdata_flag() const { return m_shaderdata_flag; }
@@ -119,9 +135,9 @@ protected:
\
class Upper##Closure : public CBSDFClosure { \
public: \
- Upper##Closure() : CBSDFClosure(TYPE) {} \
- size_t memsize() const { return sizeof(*this); } \
- const char *name() const { return #lower; } \
+ Upper##Closure() : CBSDFClosure(TYPE) \
+ { \
+ } \
\
void setup() \
{ \
@@ -129,21 +145,11 @@ public: \
m_shaderdata_flag = bsdf_##lower##_setup(&sc); \
} \
\
- bool mergeable(const ClosurePrimitive *other) const \
- { \
- return false; \
- } \
- \
void blur(float roughness) \
{ \
bsdf_##svmlower##_blur(&sc, roughness); \
} \
\
- void print_on(std::ostream &out) const \
- { \
- out << name() << " ((" << sc.N[0] << ", " << sc.N[1] << ", " << sc.N[2] << "))"; \
- } \
-\
float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const \
{ \
return bsdf_##svmlower##_eval_reflect(&sc, omega_out, omega_in, &pdf); \
@@ -178,7 +184,7 @@ static ClosureParam *bsdf_##lower##_params() \
return params; \
} \
\
-CLOSURE_PREPARE_STATIC(bsdf_##lower##_prepare, Upper##Closure)
+CCLOSURE_PREPARE_STATIC(bsdf_##lower##_prepare, Upper##Closure)
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp
index 309f5ded96d..d7d3301c0b0 100644
--- a/intern/cycles/kernel/osl/osl_services.cpp
+++ b/intern/cycles/kernel/osl/osl_services.cpp
@@ -44,6 +44,10 @@
#include "kernel_camera.h"
#include "kernel_shader.h"
+#ifdef WITH_PTEX
+#include <Ptexture.h>
+#endif
+
CCL_NAMESPACE_BEGIN
/* RenderServices implementation */
@@ -98,10 +102,18 @@ OSLRenderServices::OSLRenderServices()
{
kernel_globals = NULL;
osl_ts = NULL;
+
+#ifdef WITH_PTEX
+ size_t maxmem = 16384 * 1024;
+ ptex_cache = PtexCache::create(0, maxmem);
+#endif
}
OSLRenderServices::~OSLRenderServices()
{
+#ifdef WITH_PTEX
+ ptex_cache->release();
+#endif
}
void OSLRenderServices::thread_init(KernelGlobals *kernel_globals_, OSL::TextureSystem *osl_ts_)
@@ -776,6 +788,45 @@ bool OSLRenderServices::texture(ustring filename, TextureOpt &options,
OSL::TextureSystem *ts = osl_ts;
ShaderData *sd = (ShaderData *)(sg->renderstate);
KernelGlobals *kg = sd->osl_globals;
+
+#ifdef WITH_PTEX
+ /* todo: this is just a quick hack, only works with particular files and options */
+ if(string_endswith(filename.string(), ".ptx")) {
+ float2 uv;
+ int faceid;
+
+ if(!primitive_ptex(kg, sd, &uv, &faceid))
+ return false;
+
+ float u = uv.x;
+ float v = uv.y;
+ float dudx = 0.0f;
+ float dvdx = 0.0f;
+ float dudy = 0.0f;
+ float dvdy = 0.0f;
+
+ Ptex::String error;
+ PtexPtr<PtexTexture> r(ptex_cache->get(filename.c_str(), error));
+
+ if(!r) {
+ //std::cerr << error.c_str() << std::endl;
+ return false;
+ }
+
+ bool mipmaplerp = false;
+ float sharpness = 1.0f;
+ PtexFilter::Options opts(PtexFilter::f_bicubic, mipmaplerp, sharpness);
+ PtexPtr<PtexFilter> f(PtexFilter::getFilter(r, opts));
+
+ f->eval(result, options.firstchannel, options.nchannels, faceid, u, v, dudx, dvdx, dudy, dvdy);
+
+ for(int c = r->numChannels(); c < options.nchannels; c++)
+ result[c] = result[0];
+
+ return true;
+ }
+#endif
+
OSLThreadData *tdata = kg->osl_tdata;
OIIO::TextureSystem::Perthread *thread_info = tdata->oiio_thread_info;
diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h
index f62895047b3..21609621b1d 100644
--- a/intern/cycles/kernel/osl/osl_services.h
+++ b/intern/cycles/kernel/osl/osl_services.h
@@ -28,6 +28,10 @@
#include <OSL/oslexec.h>
#include <OSL/oslclosure.h>
+#ifdef WITH_PTEX
+class PtexCache;
+#endif
+
CCL_NAMESPACE_BEGIN
class Object;
@@ -148,6 +152,9 @@ public:
private:
KernelGlobals *kernel_globals;
OSL::TextureSystem *osl_ts;
+#ifdef WITH_PTEX
+ PtexCache *ptex_cache;
+#endif
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp
index 18e8fee4348..f2be61eb535 100644
--- a/intern/cycles/kernel/osl/osl_shader.cpp
+++ b/intern/cycles/kernel/osl/osl_shader.cpp
@@ -146,7 +146,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
if (closure->type == OSL::ClosureColor::COMPONENT) {
OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
- OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data();
+ CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
if (prim) {
ShaderClosure sc;
@@ -156,8 +156,10 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
sc.weight = weight;
#endif
- switch (prim->category()) {
- case OSL::ClosurePrimitive::BSDF: {
+ prim->setup();
+
+ switch (prim->category) {
+ case CClosurePrimitive::BSDF: {
CBSDFClosure *bsdf = (CBSDFClosure *)prim;
int scattering = bsdf->scattering();
@@ -191,7 +193,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
}
break;
}
- case OSL::ClosurePrimitive::Emissive: {
+ case CClosurePrimitive::Emissive: {
/* sample weight */
float sample_weight = fabsf(average(weight));
@@ -208,7 +210,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
}
break;
}
- case AmbientOcclusion: {
+ case CClosurePrimitive::AmbientOcclusion: {
/* sample weight */
float sample_weight = fabsf(average(weight));
@@ -224,7 +226,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
}
break;
}
- case OSL::ClosurePrimitive::Holdout: {
+ case CClosurePrimitive::Holdout: {
sc.sample_weight = 0.0f;
sc.type = CLOSURE_HOLDOUT_ID;
sc.data0 = 0.0f;
@@ -237,7 +239,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
}
break;
}
- case OSL::ClosurePrimitive::BSSRDF: {
+ case CClosurePrimitive::BSSRDF: {
CBSSRDFClosure *bssrdf = (CBSSRDFClosure *)prim;
float sample_weight = fabsf(average(weight));
@@ -280,10 +282,8 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
}
break;
}
- case OSL::ClosurePrimitive::Debug:
- break; /* not implemented */
- case OSL::ClosurePrimitive::Background:
- case OSL::ClosurePrimitive::Volume:
+ case CClosurePrimitive::Background:
+ case CClosurePrimitive::Volume:
break; /* not relevant */
}
}
@@ -332,9 +332,9 @@ static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure)
if (closure->type == OSL::ClosureColor::COMPONENT) {
OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
- OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data();
+ CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
- if (prim && prim->category() == OSL::ClosurePrimitive::Background)
+ if (prim && prim->category == CClosurePrimitive::Background)
#ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
return TO_FLOAT3(comp->w);
#else
@@ -387,7 +387,7 @@ static void flatten_volume_closure_tree(ShaderData *sd,
if (closure->type == OSL::ClosureColor::COMPONENT) {
OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
- OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data();
+ CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
if (prim) {
ShaderClosure sc;
@@ -397,8 +397,10 @@ static void flatten_volume_closure_tree(ShaderData *sd,
sc.weight = weight;
#endif
- switch (prim->category()) {
- case OSL::ClosurePrimitive::Volume: {
+ prim->setup();
+
+ switch (prim->category) {
+ case CClosurePrimitive::Volume: {
/* sample weight */
float sample_weight = fabsf(average(weight));
@@ -413,13 +415,13 @@ static void flatten_volume_closure_tree(ShaderData *sd,
sd->closure[sd->num_closure++] = sc;
break;
}
- case OSL::ClosurePrimitive::Holdout:
- case OSL::ClosurePrimitive::Debug:
+ case CClosurePrimitive::Holdout:
break; /* not implemented */
- case OSL::ClosurePrimitive::Background:
- case OSL::ClosurePrimitive::BSDF:
- case OSL::ClosurePrimitive::Emissive:
- case OSL::ClosurePrimitive::BSSRDF:
+ case CClosurePrimitive::Background:
+ case CClosurePrimitive::BSDF:
+ case CClosurePrimitive::Emissive:
+ case CClosurePrimitive::BSSRDF:
+ case CClosurePrimitive::AmbientOcclusion:
break; /* not relevant */
}
}
@@ -509,25 +511,6 @@ void OSLShader::bsdf_blur(ShaderClosure *sc, float roughness)
bsdf->blur(roughness);
}
-/* Emissive Closure */
-
-float3 OSLShader::emissive_eval(const ShaderData *sd, const ShaderClosure *sc)
-{
- OSL::EmissiveClosure *emissive = (OSL::EmissiveClosure *)sc->prim;
- OSL::Color3 emissive_eval = emissive->eval(TO_VEC3(sd->Ng), TO_VEC3(sd->I));
-
- return TO_FLOAT3(emissive_eval);
-}
-
-/* Volume Closure */
-
-float3 OSLShader::volume_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
-{
- OSL::VolumeClosure *volume = (OSL::VolumeClosure *)sc->prim;
- OSL::Color3 volume_eval = volume->eval_phase(TO_VEC3(omega_in), TO_VEC3(omega_out));
- return TO_FLOAT3(volume_eval) * sc->weight;
-}
-
/* Attributes */
int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem)
diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h
index 777ecb6af81..2520b703ab7 100644
--- a/intern/cycles/kernel/osl/osl_shader.h
+++ b/intern/cycles/kernel/osl/osl_shader.h
@@ -66,11 +66,6 @@ public:
const float3& omega_in, float& pdf);
static void bsdf_blur(ShaderClosure *sc, float roughness);
- static float3 emissive_eval(const ShaderData *sd, const ShaderClosure *sc);
-
- static float3 volume_eval_phase(const ShaderClosure *sc,
- const float3 omega_in, const float3 omega_out);
-
/* attributes */
static int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem);
};
diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h
index 47c5dc27f2b..d1d1222af44 100644
--- a/intern/cycles/kernel/shaders/stdosl.h
+++ b/intern/cycles/kernel/shaders/stdosl.h
@@ -412,13 +412,27 @@ matrix transpose (matrix m) BUILTIN;
// Pattern generation
-float step (float edge, float x) BUILTIN;
color step (color edge, color x) BUILTIN;
point step (point edge, point x) BUILTIN;
vector step (vector edge, vector x) BUILTIN;
normal step (normal edge, normal x) BUILTIN;
+float step (float edge, float x) BUILTIN;
float smoothstep (float edge0, float edge1, float x) BUILTIN;
+float aastep (float edge, float s, float dedge, float ds) {
+ // Box filtered AA step
+ float width = fabs(dedge) + fabs(ds);
+ float halfwidth = 0.5*width;
+ float e1 = edge-halfwidth;
+ return (s <= e1) ? 0.0 : ((s >= (edge+halfwidth)) ? 1.0 : (s-e1)/width);
+}
+float aastep (float edge, float s, float ds) {
+ return aastep (edge, s, filterwidth(edge), ds);
+}
+float aastep (float edge, float s) {
+ return aastep (edge, s, filterwidth(edge), filterwidth(s));
+}
+
// Derivatives and area operators
diff --git a/intern/cycles/kernel/svm/svm_fresnel.h b/intern/cycles/kernel/svm/svm_fresnel.h
index bb70a3faa2a..0a3d576cfe1 100644
--- a/intern/cycles/kernel/svm/svm_fresnel.h
+++ b/intern/cycles/kernel/svm/svm_fresnel.h
@@ -39,10 +39,12 @@ ccl_device void svm_node_layer_weight(ShaderData *sd, float *stack, uint4 node)
{
uint blend_offset = node.y;
uint blend_value = node.z;
- float blend = (stack_valid(blend_offset))? stack_load_float(stack, blend_offset): __uint_as_float(blend_value);
- uint type, out_offset;
- decode_node_uchar4(node.w, &type, &out_offset, NULL, NULL);
+ uint type, normal_offset, out_offset;
+ decode_node_uchar4(node.w, &type, &normal_offset, &out_offset, NULL);
+
+ float blend = (stack_valid(blend_offset))? stack_load_float(stack, blend_offset): __uint_as_float(blend_value);
+ float3 normal_in = (stack_valid(normal_offset))? stack_load_float3(stack, normal_offset): sd->N;
float f;
@@ -50,10 +52,10 @@ ccl_device void svm_node_layer_weight(ShaderData *sd, float *stack, uint4 node)
float eta = fmaxf(1.0f - blend, 1e-5f);
eta = (sd->flag & SD_BACKFACING)? eta: 1.0f/eta;
- f = fresnel_dielectric_cos(dot(sd->I, sd->N), eta);
+ f = fresnel_dielectric_cos(dot(sd->I, normal_in), eta);
}
else {
- f = fabsf(dot(sd->I, sd->N));
+ f = fabsf(dot(sd->I, normal_in));
if(blend != 0.5f) {
blend = clamp(blend, 0.0f, 1.0f-1e-5f);
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp
index 319616450e1..6640439eca9 100644
--- a/intern/cycles/render/attribute.cpp
+++ b/intern/cycles/render/attribute.cpp
@@ -147,6 +147,10 @@ const char *Attribute::standard_name(AttributeStandard std)
return "particle";
else if(std == ATTR_STD_CURVE_INTERCEPT)
return "curve_intercept";
+ else if(std == ATTR_STD_PTEX_FACE_ID)
+ return "ptex_face_id";
+ else if(std == ATTR_STD_PTEX_UV)
+ return "ptex_uv";
return "";
}
@@ -246,6 +250,12 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
case ATTR_STD_MOTION_POST:
attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
break;
+ case ATTR_STD_PTEX_FACE_ID:
+ attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_FACE);
+ break;
+ case ATTR_STD_PTEX_UV:
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
+ break;
default:
assert(0);
break;
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 4919222e81c..fcc92b641fd 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -217,6 +217,21 @@ ShaderNode *ImageTextureNode::clone() const
return node;
}
+void ImageTextureNode::attributes(AttributeRequestSet *attributes)
+{
+#ifdef WITH_PTEX
+ /* todo: avoid loading other texture coordinates when using ptex,
+ * and hide texture coordinate socket in the UI */
+ if (string_endswith(filename, ".ptx")) {
+ /* ptex */
+ attributes->add(ATTR_STD_PTEX_FACE_ID);
+ attributes->add(ATTR_STD_PTEX_UV);
+ }
+#endif
+
+ ShaderNode::attributes(attributes);
+}
+
void ImageTextureNode::compile(SVMCompiler& compiler)
{
ShaderInput *vector_in = input("Vector");
@@ -352,6 +367,19 @@ ShaderNode *EnvironmentTextureNode::clone() const
return node;
}
+void EnvironmentTextureNode::attributes(AttributeRequestSet *attributes)
+{
+#ifdef WITH_PTEX
+ if (string_endswith(filename, ".ptx")) {
+ /* ptex */
+ attributes->add(ATTR_STD_PTEX_FACE_ID);
+ attributes->add(ATTR_STD_PTEX_UV);
+ }
+#endif
+
+ ShaderNode::attributes(attributes);
+}
+
void EnvironmentTextureNode::compile(SVMCompiler& compiler)
{
ShaderInput *vector_in = input("Vector");
@@ -3198,8 +3226,12 @@ LayerWeightNode::LayerWeightNode()
void LayerWeightNode::compile(SVMCompiler& compiler)
{
+ ShaderInput *normal_in = input("Normal");
ShaderInput *blend_in = input("Blend");
+ if(normal_in->link)
+ compiler.stack_assign(normal_in);
+
if(blend_in->link)
compiler.stack_assign(blend_in);
@@ -3207,14 +3239,14 @@ void LayerWeightNode::compile(SVMCompiler& compiler)
if(!fresnel_out->links.empty()) {
compiler.stack_assign(fresnel_out);
compiler.add_node(NODE_LAYER_WEIGHT, blend_in->stack_offset, __float_as_int(blend_in->value.x),
- compiler.encode_uchar4(NODE_LAYER_WEIGHT_FRESNEL, fresnel_out->stack_offset));
+ compiler.encode_uchar4(NODE_LAYER_WEIGHT_FRESNEL, normal_in->stack_offset, fresnel_out->stack_offset));
}
ShaderOutput *facing_out = output("Facing");
if(!facing_out->links.empty()) {
compiler.stack_assign(facing_out);
compiler.add_node(NODE_LAYER_WEIGHT, blend_in->stack_offset, __float_as_int(blend_in->value.x),
- compiler.encode_uchar4(NODE_LAYER_WEIGHT_FACING, facing_out->stack_offset));
+ compiler.encode_uchar4(NODE_LAYER_WEIGHT_FACING, normal_in->stack_offset, facing_out->stack_offset));
}
}
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 430c37158f4..d7a110af83b 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -66,6 +66,7 @@ public:
SHADER_NODE_NO_CLONE_CLASS(ImageTextureNode)
~ImageTextureNode();
ShaderNode *clone() const;
+ void attributes(AttributeRequestSet *attributes);
ImageManager *image_manager;
int slot;
@@ -87,6 +88,7 @@ public:
SHADER_NODE_NO_CLONE_CLASS(EnvironmentTextureNode)
~EnvironmentTextureNode();
ShaderNode *clone() const;
+ void attributes(AttributeRequestSet *attributes);
ImageManager *image_manager;
int slot;
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index d0ed95cca34..4ed8ece0556 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -724,13 +724,17 @@ void OSLCompiler::generate_nodes(const set<ShaderNode*>& nodes)
} while(!nodes_done);
}
-void OSLCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType type)
+OSL::ShadingAttribStateRef OSLCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType type)
{
OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
current_type = type;
+#if OSL_LIBRARY_VERSION_CODE >= 10501
+ OSL::ShadingAttribStateRef group = ss->ShaderGroupBegin(shader->name.c_str());
+#else
ss->ShaderGroupBegin(shader->name.c_str());
+#endif
ShaderNode *output = graph->output();
set<ShaderNode*> dependencies;
@@ -757,12 +761,19 @@ void OSLCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
assert(0);
ss->ShaderGroupEnd();
+
+#if OSL_LIBRARY_VERSION_CODE >= 10501
+ return group;
+#else
+ OSL::ShadingAttribStateRef group = ss->state();
+ ss->clear_state();
+ return group;
+#endif
}
void OSLCompiler::compile(OSLGlobals *og, Shader *shader)
{
if(shader->need_update) {
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
ShaderGraph *graph = shader->graph;
ShaderNode *output = (graph)? graph->output(): NULL;
@@ -788,19 +799,13 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader)
/* generate surface shader */
if(shader->used && graph && output->input("Surface")->link) {
- compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
- shader->osl_surface_ref = ss->state();
+ shader->osl_surface_ref = compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
- if(shader->graph_bump) {
- ss->clear_state();
- compile_type(shader, shader->graph_bump, SHADER_TYPE_SURFACE);
- shader->osl_surface_bump_ref = ss->state();
- }
+ if(shader->graph_bump)
+ shader->osl_surface_bump_ref = compile_type(shader, shader->graph_bump, SHADER_TYPE_SURFACE);
else
shader->osl_surface_bump_ref = shader->osl_surface_ref;
- ss->clear_state();
-
shader->has_surface = true;
}
else {
@@ -810,21 +815,16 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader)
/* generate volume shader */
if(shader->used && graph && output->input("Volume")->link) {
- compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
+ shader->osl_volume_ref = compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
shader->has_volume = true;
-
- shader->osl_volume_ref = ss->state();
- ss->clear_state();
}
else
shader->osl_volume_ref = OSL::ShadingAttribStateRef();
/* generate displacement shader */
if(shader->used && graph && output->input("Displacement")->link) {
- compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
+ shader->osl_displacement_ref = compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
shader->has_displacement = true;
- shader->osl_displacement_ref = ss->state();
- ss->clear_state();
}
else
shader->osl_displacement_ref = OSL::ShadingAttribStateRef();
diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h
index d6e514bdcaf..5824e2ace64 100644
--- a/intern/cycles/render/osl.h
+++ b/intern/cycles/render/osl.h
@@ -142,14 +142,16 @@ public:
ImageManager *image_manager;
private:
+#ifdef WITH_OSL
string id(ShaderNode *node);
- void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
+ OSL::ShadingAttribStateRef compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
bool node_skip_input(ShaderNode *node, ShaderInput *input);
string compatible_name(ShaderNode *node, ShaderInput *input);
string compatible_name(ShaderNode *node, ShaderOutput *output);
void find_dependencies(set<ShaderNode*>& dependencies, ShaderInput *input);
void generate_nodes(const set<ShaderNode*>& nodes);
+#endif
void *shadingsys;
void *manager;
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 6c15849d815..0805a685467 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -95,7 +95,7 @@ Session::~Session()
wait();
}
- if(display && params.output_path != "") {
+ if(display && !params.output_path.empty()) {
tonemap();
progress.set_status("Writing Image", params.output_path);
@@ -242,7 +242,7 @@ void Session::run_gpu()
/* update scene */
update_scene();
- if(device->error_message() != "")
+ if(!device->error_message().empty())
progress.set_cancel(device->error_message());
if(progress.get_cancel())
@@ -263,7 +263,7 @@ void Session::run_gpu()
device->task_wait();
- if(device->error_message() != "")
+ if(!device->error_message().empty())
progress.set_cancel(device->error_message());
/* update status and timing */
@@ -283,7 +283,7 @@ void Session::run_gpu()
}
}
- if(device->error_message() != "")
+ if(!device->error_message().empty())
progress.set_cancel(device->error_message());
tiles_written = update_progressive_refine(progress.get_cancel());
@@ -531,7 +531,7 @@ void Session::run_cpu()
/* update scene */
update_scene();
- if(device->error_message() != "")
+ if(!device->error_message().empty())
progress.set_cancel(device->error_message());
if(progress.get_cancel())
@@ -549,7 +549,7 @@ void Session::run_cpu()
if(!params.background)
need_tonemap = true;
- if(device->error_message() != "")
+ if(!device->error_message().empty())
progress.set_cancel(device->error_message());
}
@@ -571,7 +571,7 @@ void Session::run_cpu()
tonemap();
}
- if(device->error_message() != "")
+ if(!device->error_message().empty())
progress.set_cancel(device->error_message());
tiles_written = update_progressive_refine(progress.get_cancel());
@@ -592,7 +592,7 @@ void Session::run()
if(!device->load_kernels(params.experimental)) {
string message = device->error_message();
- if(message == "")
+ if(message.empty())
message = "Failed loading render kernel, see console for errors";
progress.set_status("Error", message);
@@ -796,7 +796,7 @@ void Session::update_status_time(bool show_pause, bool show_done)
}
else {
status = substatus;
- substatus = "";
+ substatus.clear();
}
progress.set_status(status, substatus);
diff --git a/intern/cycles/subd/CMakeLists.txt b/intern/cycles/subd/CMakeLists.txt
index 838776d60bf..2641f6d9c0c 100644
--- a/intern/cycles/subd/CMakeLists.txt
+++ b/intern/cycles/subd/CMakeLists.txt
@@ -12,26 +12,17 @@ set(INC_SYS
)
set(SRC
- subd_build.cpp
subd_dice.cpp
subd_mesh.cpp
subd_patch.cpp
- subd_ring.cpp
subd_split.cpp
- subd_stencil.cpp
)
set(SRC_HEADERS
- subd_build.h
subd_dice.h
- subd_edge.h
- subd_face.h
subd_mesh.h
subd_patch.h
- subd_ring.h
subd_split.h
- subd_stencil.h
- subd_vert.h
)
include_directories(${INC})
diff --git a/intern/cycles/subd/subd_build.cpp b/intern/cycles/subd/subd_build.cpp
deleted file mode 100644
index f3c2837c37c..00000000000
--- a/intern/cycles/subd/subd_build.cpp
+++ /dev/null
@@ -1,669 +0,0 @@
-/*
- * Copyright 2006, NVIDIA Corporation Ignacio Castano <icastano@nvidia.com>
- *
- * Modifications copyright (c) 2011, Blender Foundation. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "subd_build.h"
-#include "subd_edge.h"
-#include "subd_face.h"
-#include "subd_ring.h"
-#include "subd_mesh.h"
-#include "subd_patch.h"
-#include "subd_stencil.h"
-#include "subd_vert.h"
-
-#include "util_algorithm.h"
-#include "util_debug.h"
-#include "util_math.h"
-#include "util_string.h"
-
-CCL_NAMESPACE_BEGIN
-
-/* Subd Builder */
-
-SubdBuilder *SubdBuilder::create(bool linear)
-{
- if(linear)
- return new SubdLinearBuilder();
- else
- return new SubdAccBuilder();
-}
-
-/* Gregory ACC Stencil */
-
-class GregoryAccStencil {
-public:
- SubdFaceRing *ring;
- StencilMask stencil[20];
-
- GregoryAccStencil(SubdFaceRing *ring_)
- {
- ring = ring_;
-
- for(int i = 0; i < 20; i++)
- stencil[i].resize(ring->num_verts());
- }
-
- StencilMask& get(int i)
- {
- assert(i < 20);
- return stencil[i];
- }
-
- float& get(int i, SubdVert *vert)
- {
- assert(i < 20);
- return stencil[i][ring->vert_index(vert)];
- }
-};
-
-static float pseudoValence(SubdVert *vert)
-{
- float valence = (float)vert->valence();
-
- if(vert->is_boundary()) {
- /* we treat boundary verts as being half a closed mesh. corners are
- * special case. n = 4 for corners and n = 2*(n-1) for boundaries. */
- if(valence == 2) return 4;
- return (valence - 1)*2;
- }
-
- return valence;
-}
-
-/* Subd ACC Builder */
-
-SubdAccBuilder::SubdAccBuilder()
-{
-}
-
-SubdAccBuilder::~SubdAccBuilder()
-{
-}
-
-Patch *SubdAccBuilder::run(SubdFace *face)
-{
- SubdFaceRing ring(face, face->edge);
- GregoryAccStencil stencil(&ring);
- float3 position[20];
-
- computeCornerStencil(&ring, &stencil);
- computeEdgeStencil(&ring, &stencil);
- computeInteriorStencil(&ring, &stencil);
-
- ring.evaluate_stencils(position, stencil.stencil, 20);
-
- if(face->num_edges() == 3) {
- GregoryTrianglePatch *patch = new GregoryTrianglePatch();
- memcpy(patch->hull, position, sizeof(float3)*20);
- return patch;
- }
- else if(face->num_edges() == 4) {
- GregoryQuadPatch *patch = new GregoryQuadPatch();
- memcpy(patch->hull, position, sizeof(float3)*20);
- return patch;
- }
-
- assert(0); /* n-gons should have been split already */
- return NULL;
-}
-
-/* Gregory Patch */
-
-void SubdAccBuilder::computeCornerStencil(SubdFaceRing *ring, GregoryAccStencil *stencil)
-{
- const int cornerIndices[7] = {8, 11, 19, 16, 6, 9, 12};
- int primitiveOffset = ring->is_quad()? 0: 4;
-
- SubdEdge *firstEdge = ring->firstEdge();
-
- /* compute corner control points */
- int v = 0;
-
- for(SubdFace::EdgeIterator it(firstEdge); !it.isDone(); it.advance(), v++) {
- SubdVert *vert = it.current()->from();
- int valence = vert->valence();
- int cid = cornerIndices[primitiveOffset+v];
-
- if(vert->is_boundary()) {
- /* compute vertex limit position */
- SubdEdge *edge0 = vert->edge;
- SubdEdge *edge1 = vert->edge->prev;
-
- assert(edge0->face == NULL);
- assert(edge0->to() != vert);
- assert(edge1->face == NULL);
- assert(edge1->from() != vert);
-
- stencil->get(cid, vert) = 2.0f/3.0f;
- stencil->get(cid, edge0->to()) = 1.0f/6.0f;
- stencil->get(cid, edge1->from()) = 1.0f/6.0f;
-
- assert(stencil->get(cid).is_normalized());
- }
- else {
- stencil->get(cid, vert) = 3.0f*valence*valence;
-
- for(SubdVert::EdgeIterator eit(vert->edge); !eit.isDone(); eit.advance()) {
- SubdEdge *edge = eit.current();
- assert(vert->co == edge->from()->co);
-
- stencil->get(cid, edge->to()) = 12.0f;
-
- if(SubdFaceRing::is_triangle(edge->face)) {
- /* distribute weight to all verts */
- stencil->get(cid, vert) += 1.0f;
- stencil->get(cid, edge->to()) += 1.0f;
- stencil->get(cid, edge->next->to()) += 1.0f;
- }
- else
- stencil->get(cid, edge->next->to()) = 3.0f;
- }
-
- /* normalize stencil. */
- stencil->get(cid).normalize();
- }
- }
-}
-
-void SubdAccBuilder::computeEdgeStencil(SubdFaceRing *ring, GregoryAccStencil *stencil)
-{
- const int cornerIndices[7] = {8, 11, 19, 16, 6, 9, 12};
- const int edge1Indices[7] = {9, 13, 18, 14, 7, 10, 13};
- const int edge2Indices[7] = {12, 10, 15, 17, 14, 8, 11};
- int primitiveOffset = ring->is_quad()? 0: 4;
-
- float tangentScales[14] = {
- 0.0f, 0.0f, 0.0f, 0.667791f, 1.0f,
- 1.11268f, 1.1284f, 1.10289f, 1.06062f,
- 1.01262f, 0.963949f, 0.916926f, 0.872541f, 0.831134f
- };
-
- SubdEdge *firstEdge = ring->firstEdge();
-
- /* compute corner / edge control points */
- int v = 0;
-
- for(SubdFace::EdgeIterator it(firstEdge); !it.isDone(); it.advance(), v++) {
- SubdVert *vert = it.current()->from();
- int valence = vert->valence();
- int cid = cornerIndices[primitiveOffset+v];
-
- int i1 = 0, i2 = 0, j = 0;
-
- for(SubdVert::EdgeIterator eit(vert->edge); !eit.isDone(); eit.advance(), j++) {
- SubdEdge *edge = eit.current();
-
- /* find index of "our" edge for edge control points */
- if(edge == it.current())
- i1 = j;
- if(edge == it.current()->prev->pair)
- i2 = j;
- }
-
- if(vert->is_boundary()) {
- int num_verts = ring->num_verts();
- StencilMask r0(num_verts);
- StencilMask r1(num_verts);
-
- computeBoundaryTangentStencils(ring, vert, r0, r1);
-
- int k = valence - 1;
- float omega = M_PI_F / k;
-
- int eid1 = edge1Indices[primitiveOffset + v];
- int eid2 = edge2Indices[primitiveOffset + v];
-
- if(it.current()->is_boundary()) {
- assert(it.current()->from() == vert);
-
- stencil->get(eid1, vert) = 2.0f / 3.0f;
- stencil->get(eid1, it.current()->to()) = 1.0f / 3.0f;
-
- assert(stencil->get(eid1).is_normalized());
-
- if(valence == 2) {
- for(int i = 0; i < num_verts; i++)
- stencil->get(eid1)[i] += r0[i] * 0.0001f;
- }
- }
- else {
- stencil->get(eid1) = stencil->get(cid);
-
- /* compute index of it.current() around vert */
- int idx = 0;
-
- for(SubdVert::EdgeIterator eit(vert->edges()); !eit.isDone(); eit.advance(), idx++)
- if(eit.current() == it.current())
- break;
-
- assert(idx != valence);
-
- float c = cosf(idx * omega);
- float s = sinf(idx * omega);
-
- for(int i = 0; i < num_verts; i++)
- stencil->get(eid1)[i] += (r0[i] * s + r1[i] * c) / 3.0f;
- }
-
- if(it.current()->prev->is_boundary()) {
- assert(it.current()->prev->pair->from() == vert);
-
- stencil->get(eid2, vert) = 2.0f / 3.0f;
- stencil->get(eid2, it.current()->prev->pair->to()) = 1.0f / 3.0f;
-
- assert(stencil->get(eid2).is_normalized());
-
- if(valence == 2) {
- for(int i = 0; i < num_verts; i++)
- stencil->get(eid2)[i] += r0[i] * 0.0001f;
- }
- }
- else {
- stencil->get(eid2) = stencil->get(cid);
-
- /* compute index of it.current() around vert */
- int idx = 0;
-
- for(SubdVert::EdgeIterator eit(vert->edges()); !eit.isDone(); eit.advance(), idx++)
- if(eit.current() == it.current()->prev->pair)
- break;
-
- assert(idx != valence);
-
- float c = cosf(idx * omega);
- float s = sinf(idx * omega);
-
- for(int i = 0; i < num_verts; i++)
- stencil->get(eid2)[i] += (r0[i] * s + r1[i] * c) / 3;
- }
- }
- else {
- float costerm = cosf(M_PI_F / valence);
- float sqrtterm = sqrtf(4.0f + costerm*costerm);
-
- /* float tangentScale = 1.0f; */
- float tangentScale = tangentScales[min(valence, 13U)];
-
- float alpha = (1.0f + costerm / sqrtterm) / (3.0f * valence) * tangentScale;
- float beta = 1.0f / (3.0f * valence * sqrtterm) * tangentScale;
-
-
- int eid1 = edge1Indices[primitiveOffset + v];
- int eid2 = edge2Indices[primitiveOffset + v];
-
- stencil->get(eid1) = stencil->get(cid);
- stencil->get(eid2) = stencil->get(cid);
-
- j = 0;
- for(SubdVert::EdgeIterator eit(vert->edges()); !eit.isDone(); eit.advance(), j++) {
- SubdEdge *edge = eit.current();
- assert(vert->co == edge->from()->co);
-
- float costerm1_a = cosf(M_PI_F * 2 * (j-i1) / valence);
- float costerm1_b = cosf(M_PI_F * (2 * (j-i1)-1) / valence); /* -1 instead of +1 b/c of edge->next->to() */
-
- float costerm2_a = cosf(M_PI_F * 2 * (j-i2) / valence);
- float costerm2_b = cosf(M_PI_F * (2 * (j-i2)-1) / valence); /* -1 instead of +1 b/c of edge->next->to() */
-
-
- stencil->get(eid1, edge->to()) += alpha * costerm1_a;
- stencil->get(eid2, edge->to()) += alpha * costerm2_a;
-
- if(SubdFaceRing::is_triangle(edge->face)) {
- /* @@ this probably does not provide watertight results!! (1/3 + 1/3 + 1/3 != 1) */
-
- /* distribute weight to all verts */
- stencil->get(eid1, vert) += beta * costerm1_b / 3.0f;
- stencil->get(eid1, edge->to()) += beta * costerm1_b / 3.0f;
- stencil->get(eid1, edge->next->to()) += beta * costerm1_b / 3.0f;
-
- stencil->get(eid2, vert) += beta * costerm2_b / 3.0f;
- stencil->get(eid2, edge->to()) += beta * costerm2_b / 3.0f;
- stencil->get(eid2, edge->next->to()) += beta * costerm2_b / 3.0f;
- }
- else {
- stencil->get(eid1, edge->next->to()) += beta * costerm1_b;
- stencil->get(eid2, edge->next->to()) += beta * costerm2_b;
- }
- }
- }
- }
-}
-
-void SubdAccBuilder::computeInteriorStencil(SubdFaceRing *ring, GregoryAccStencil *stencil)
-{
- static int corner1Indices[7] = {8, 11, 19, 16, 6, 9, 12};
- static int corner2Indices[7] = {11, 19, 16, 8, 9, 12, 6};
- static int edge1Indices[7] = {9, 13, 18, 14, 7, 10, 13};
- static int edge2Indices[7] = {10, 15, 17, 12, 8, 11, 14};
- static int interior1Indices[7] = {1, 3, 6, 4, 1, 3, 5};
- static int interior2Indices[7] = {2, 7, 5, 0, 2, 4, 0};
-
- int primitiveOffset = ring->is_quad()? 0: 4;
-
- SubdFace * face = ring->face();
- SubdEdge *firstEdge = ring->firstEdge();
-
- /* interior control points */
- int v = 0;
- for(SubdFace::EdgeIterator it(firstEdge); !it.isDone(); it.advance(), v++) {
- SubdEdge *edge = it.current();
-
- if(edge->is_boundary()) {
- float valence1 = pseudoValence(edge->from());
- float valence2 = pseudoValence(edge->to());
-
- float weights1[4];
- float weights2[4];
-
- if(ring->is_quad()) {
- weights1[0] = 3 * valence1;
- weights1[1] = 6;
- weights1[2] = 3;
- weights1[3] = 6;
-
- weights2[0] = 6;
- weights2[1] = 3 * valence2;
- weights2[2] = 6;
- weights2[3] = 3;
- }
- else {
- assert(ring->is_triangle());
- weights1[0] = 3 * valence1 + 1;
- weights1[1] = 7;
- weights1[2] = 7;
-
- weights2[0] = 7;
- weights2[1] = 3 * valence2 + 1;
- weights2[2] = 7;
- }
-
- int idx1 = interior1Indices[primitiveOffset+v];
- int idx2 = interior2Indices[primitiveOffset+v];
-
- int i = 0;
- for(SubdFace::EdgeIterator it_sub(face->edges(edge)); !it_sub.isDone(); it_sub.advance(), i++) {
- SubdVert *vert = it_sub.current()->from();
- stencil->get(idx1, vert) += weights1[i];
- stencil->get(idx2, vert) += weights2[i];
- }
-
- stencil->get(idx1).normalize();
- stencil->get(idx2).normalize();
- }
- else {
- SubdVert *e0 = edge->from();
- float costerm0 = cosf(M_2PI_F / pseudoValence(e0));
-
- SubdVert *f0 = edge->to();
- float costerm1 = cosf(M_2PI_F / pseudoValence(f0));
-
- /* p0 +------+ q0
- * | |
- * f0 +======+ e0 <=== current edge
- * | |
- * p1 +------+ q1
- */
-
- SubdVert *q0 = edge->next->to();
- SubdVert *p0 = edge->prev->from();
-
- SubdVert *p1 = edge->pair->next->to();
- SubdVert *q1 = edge->pair->prev->from();
-
-
- StencilMask x(ring->num_verts());
- StencilMask y(ring->num_verts());
-
- for(int i = 0; i < ring->num_verts(); i++) {
- x[i] =
- (costerm1 * stencil->get(corner1Indices[primitiveOffset+v])[i] -
- (2*costerm0 + costerm1) * stencil->get(edge1Indices[primitiveOffset+v])[i] +
- 2*costerm0 * stencil->get(edge2Indices[primitiveOffset+v])[i]) / 3.0f;
- }
-
- /* y = (2*( midedgeA1 - midedgeB1) + 4*(centroidA - centroidB))/18.0f; */
- y[ring->vert_index(p0)] = 1;
- y[ring->vert_index(p1)] = -1;
-
- /* add centroidA */
- if(ring->is_triangle()) {
- y[ring->vert_index(p0)] += 4.0f / 3.0f;
- y[ring->vert_index(e0)] += 4.0f / 3.0f;
- y[ring->vert_index(f0)] += 4.0f / 3.0f;
- }
- else {
- y[ring->vert_index(p0)] += 1;
- y[ring->vert_index(q0)] += 1;
- y[ring->vert_index(e0)] += 1;
- y[ring->vert_index(f0)] += 1;
- }
-
- /* sub centroidB */
- if(SubdFaceRing::is_triangle(edge->pair->face)) {
- y[ring->vert_index(p1)] -= 4.0f / 3.0f;
- y[ring->vert_index(e0)] -= 4.0f / 3.0f;
- y[ring->vert_index(f0)] -= 4.0f / 3.0f;
-
- }
- else {
- y[ring->vert_index(p1)] -= 1;
- y[ring->vert_index(q1)] -= 1;
- y[ring->vert_index(e0)] -= 1;
- y[ring->vert_index(f0)] -= 1;
- }
-
- y /= 18.0f;
-
- if(ring->is_triangle()) {
- x *= 3.0f / 4.0f;
- y *= 3.0f / 4.0f;
- }
-
- /* this change makes the triangle boundaries smoother, but distorts the quads next to them */
-#if 0
- if(ring->is_triangle() || SubdFaceRing::is_triangle(edge->pair->face)) {
- y *= 4.0f / 3.0f;
- }
-#endif
-
- stencil->get(interior1Indices[primitiveOffset+v]) = stencil->get(edge1Indices[primitiveOffset+v]);
- stencil->get(interior1Indices[primitiveOffset+v]) += x;
- stencil->get(interior1Indices[primitiveOffset+v]) += y;
-
- for(int i = 0; i < ring->num_verts(); i++) {
- x[i] =
- (costerm0 * stencil->get(corner2Indices[primitiveOffset+v])[i] -
- (2*costerm1 + costerm0) * stencil->get(edge2Indices[primitiveOffset+v])[i] +
- 2*costerm1 * stencil->get(edge1Indices[primitiveOffset+v])[i]) / 3.0f;
- }
-
- /* y = (2*( midedgeA2 - midedgeB2) + 4*(centroidA - centroidB))/18.0f; */
- y = 0.0f;
-
- /* (2*( midedgeA2 - midedgeB2) */
- y[ring->vert_index(q0)] = 1;
- y[ring->vert_index(q1)] = -1;
-
- /* add centroidA */
- if(ring->is_triangle()) {
- y[ring->vert_index(p0)] += 4.0f / 3.0f;
- y[ring->vert_index(e0)] += 4.0f / 3.0f;
- y[ring->vert_index(f0)] += 4.0f / 3.0f;
- }
- else {
- y[ring->vert_index(p0)] += 1;
- y[ring->vert_index(q0)] += 1;
- y[ring->vert_index(e0)] += 1;
- y[ring->vert_index(f0)] += 1;
- }
-
- /* sub centroidB */
- if(SubdFaceRing::is_triangle(edge->pair->face)) {
- y[ring->vert_index(p1)] -= 4.0f / 3.0f;
- y[ring->vert_index(e0)] -= 4.0f / 3.0f;
- y[ring->vert_index(f0)] -= 4.0f / 3.0f;
-
- }
- else {
- y[ring->vert_index(p1)] -= 1;
- y[ring->vert_index(q1)] -= 1;
- y[ring->vert_index(e0)] -= 1;
- y[ring->vert_index(f0)] -= 1;
- }
-
- y /= 18.0f;
-
- if(ring->is_triangle()) {
- x *= 3.0f / 4.0f;
- y *= 3.0f / 4.0f;
- }
-
- /* this change makes the triangle boundaries smoother, but distorts the quads next to them. */
-#if 0
- if(ring->is_triangle() || SubdFaceRing::is_triangle(edge->pair->face))
- y *= 4.0f / 3.0f;
-#endif
-
- stencil->get(interior2Indices[primitiveOffset+v]) = stencil->get(edge2Indices[primitiveOffset+v]);
- stencil->get(interior2Indices[primitiveOffset+v]) += x;
- stencil->get(interior2Indices[primitiveOffset+v]) += y;
- }
- }
-}
-
-void SubdAccBuilder::computeBoundaryTangentStencils(SubdFaceRing *ring, SubdVert *vert, StencilMask & r0, StencilMask & r1)
-{
- assert(vert->is_boundary());
- assert(r0.size() == ring->num_verts());
- assert(r1.size() == ring->num_verts());
-
- SubdEdge *edge0 = vert->edge;
- assert(edge0->face == NULL);
- assert(edge0->to() != vert);
-
- SubdEdge *edgek = vert->edge->prev;
- assert(edgek->face == NULL);
- assert(edgek->from() != vert);
-
- int valence = vert->valence();
-
- int k = valence - 1;
- float omega = M_PI_F / k;
- float s = sinf(omega);
- float c = cosf(omega);
-
- float factor = 1.0f / (3 * k + c);
-
- float gamma = -4 * s * factor;
- r0[ring->vert_index(vert)] = gamma;
- /* r1[ring->vert_index(vert)] = 0; */
-
- float salpha0 = -((1 + 2 * c) * sqrtf(1 + c)) * factor / sqrtf(1 - c);
- float calpha0 = 1.0f / 2.0f;
-
- r0[ring->vert_index(edge0->to())] = salpha0;
- r1[ring->vert_index(edge0->to())] = calpha0;
-
- float salphak = salpha0;
- float calphak = -1.0f / 2.0f;
-
- r0[ring->vert_index(edgek->from())] = salphak;
- r1[ring->vert_index(edgek->from())] = calphak;
-
- int j = 0;
- for(SubdVert::EdgeIterator it(vert->edges()); !it.isDone(); it.advance(), j++) {
- SubdEdge *edge = it.current();
-
- if(j == k) break;
-
- SubdVert *p = edge->to();
- SubdVert *q = edge->pair->prev->from();
-
- float alphaj = 4 * sinf(j * omega) * factor;
- float betaj = (sinf(j * omega) + sinf((j + 1) * omega)) * factor;
-
- if(j != 0)
- r0[ring->vert_index(p)] += alphaj;
-
- if(edge->pair->prev->prev->prev == edge->pair) {
- r0[ring->vert_index(vert)] += betaj / 3.0f;
- r0[ring->vert_index(edge->pair->from())] += betaj / 3.0f;
- r0[ring->vert_index(q)] += betaj / 3.0f;
- }
- else
- r0[ring->vert_index(q)] += betaj;
- }
-
- if(valence == 2) {
- /* r0 perpendicular to r1 */
- r0[ring->vert_index(vert)] = -4.0f / 3.0f;
- r0[ring->vert_index(edgek->from())] = 1.0f / 2.0f;
- r0[ring->vert_index(edge0->to())] = 1.0f / 2.0f;
- r0[ring->vert_index(edge0->next->to())] = 1.0f / 3.0f;
- }
-}
-
-/* Subd Linear Builder */
-
-SubdLinearBuilder::SubdLinearBuilder()
-{
-}
-
-SubdLinearBuilder::~SubdLinearBuilder()
-{
-}
-
-Patch *SubdLinearBuilder::run(SubdFace *face)
-{
- Patch *patch;
- float3 *hull;
-
- if(face->num_edges() == 3) {
- LinearTrianglePatch *lpatch = new LinearTrianglePatch();
- hull = lpatch->hull;
- patch = lpatch;
- }
- else if(face->num_edges() == 4) {
- LinearQuadPatch *lpatch = new LinearQuadPatch();
- hull = lpatch->hull;
- patch = lpatch;
- }
- else {
- assert(0); /* n-gons should have been split already */
- return NULL;
- }
-
- int i = 0;
-
- for(SubdFace::EdgeIterator it(face->edge); !it.isDone(); it.advance())
- hull[i++] = it.current()->from()->co;
-
- if(face->num_edges() == 4)
- swap(hull[2], hull[3]);
-
- return patch;
-}
-
-CCL_NAMESPACE_END
-
diff --git a/intern/cycles/subd/subd_build.h b/intern/cycles/subd/subd_build.h
deleted file mode 100644
index 8353fb5993a..00000000000
--- a/intern/cycles/subd/subd_build.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2011-2013 Blender Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-#ifndef __SUBD_BUILD_H__
-#define __SUBD_BUILD_H__
-
-CCL_NAMESPACE_BEGIN
-
-class SubdFace;
-class SubdFaceRing;
-class SubdVert;
-class GregoryAccStencil;
-class Patch;
-class StencilMask;
-
-/* Builder */
-
-class SubdBuilder
-{
-public:
- virtual ~SubdBuilder() {};
- virtual Patch *run(SubdFace *face) = 0;
- static SubdBuilder *create(bool linear);
-};
-
-/* Approximate Catmull Clark using Loop's approximation */
-
-class SubdAccBuilder : public SubdBuilder
-{
-public:
- SubdAccBuilder();
- ~SubdAccBuilder();
-
- Patch *run(SubdFace *face);
-
-protected:
- /* Gregory Patch */
- void computeCornerStencil(SubdFaceRing *ring, GregoryAccStencil *stencil);
- void computeEdgeStencil(SubdFaceRing *ring, GregoryAccStencil *stencil);
- void computeInteriorStencil(SubdFaceRing *ring, GregoryAccStencil *stencil);
- void computeBoundaryTangentStencils(SubdFaceRing *ring,
- SubdVert *vert,
- StencilMask & r0, StencilMask & r1);
-};
-
-/* Linear Subdivision */
-
-class SubdLinearBuilder : public SubdBuilder
-{
-public:
- SubdLinearBuilder();
- ~SubdLinearBuilder();
-
- Patch *run(SubdFace *face);
-};
-
-CCL_NAMESPACE_END
-
-#endif /* __SUBD_BUILD_H__ */
-
diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp
index a42a2fc833b..05ff5ca4b65 100644
--- a/intern/cycles/subd/subd_dice.cpp
+++ b/intern/cycles/subd/subd_dice.cpp
@@ -26,22 +26,25 @@ CCL_NAMESPACE_BEGIN
/* EdgeDice Base */
-EdgeDice::EdgeDice(Mesh *mesh_, int shader_, bool smooth_, float dicing_rate_)
+EdgeDice::EdgeDice(const SubdParams& params_)
+: params(params_)
{
- mesh = mesh_;
mesh_P = NULL;
mesh_N = NULL;
vert_offset = 0;
- dicing_rate = dicing_rate_;
- shader = shader_;
- smooth = smooth_;
- camera = NULL;
- mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
+ params.mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
+
+ if(params.ptex) {
+ params.mesh->attributes.add(ATTR_STD_PTEX_UV);
+ params.mesh->attributes.add(ATTR_STD_PTEX_FACE_ID);
+ }
}
void EdgeDice::reserve(int num_verts, int num_tris)
{
+ Mesh *mesh = params.mesh;
+
vert_offset = mesh->verts.size();
tri_offset = mesh->triangles.size();
@@ -60,20 +63,38 @@ int EdgeDice::add_vert(Patch *patch, float2 uv)
patch->eval(&P, &dPdu, &dPdv, uv.x, uv.y);
N = normalize(cross(dPdu, dPdv));
- assert(vert_offset < mesh->verts.size());
+ assert(vert_offset < params.mesh->verts.size());
mesh_P[vert_offset] = P;
mesh_N[vert_offset] = N;
+ if(params.ptex) {
+ Attribute *attr_ptex_uv = params.mesh->attributes.add(ATTR_STD_PTEX_UV);
+ params.mesh->attributes.reserve();
+
+ float3 *ptex_uv = attr_ptex_uv->data_float3();
+ ptex_uv[vert_offset] = make_float3(uv.x, uv.y, 0.0f);
+ }
+
return vert_offset++;
}
-void EdgeDice::add_triangle(int v0, int v1, int v2)
+void EdgeDice::add_triangle(Patch *patch, int v0, int v1, int v2)
{
- mesh->add_triangle(v0, v1, v2, shader, smooth);
+ params.mesh->add_triangle(v0, v1, v2, params.shader, params.smooth);
+
+ if(params.ptex) {
+ Attribute *attr_ptex_face_id = params.mesh->attributes.add(ATTR_STD_PTEX_FACE_ID);
+ params.mesh->attributes.reserve();
+
+ float *ptex_face_id = attr_ptex_face_id->data_float();
+ ptex_face_id[tri_offset] = (float)patch->ptex_face_id();
+ }
+
+ tri_offset++;
}
-void EdgeDice::stitch_triangles(vector<int>& outer, vector<int>& inner)
+void EdgeDice::stitch_triangles(Patch *patch, vector<int>& outer, vector<int>& inner)
{
if(inner.size() == 0 || outer.size() == 0)
return; // XXX avoid crashes for Mu or Mv == 1, missing polygons
@@ -106,14 +127,14 @@ void EdgeDice::stitch_triangles(vector<int>& outer, vector<int>& inner)
v2 = inner[++i];
}
- add_triangle(v0, v1, v2);
+ add_triangle(patch, v0, v1, v2);
}
}
/* QuadDice */
-QuadDice::QuadDice(Mesh *mesh_, int shader_, bool smooth_, float dicing_rate_)
-: EdgeDice(mesh_, shader_, smooth_, dicing_rate_)
+QuadDice::QuadDice(const SubdParams& params_)
+: EdgeDice(params_)
{
}
@@ -121,7 +142,8 @@ void QuadDice::reserve(EdgeFactors& ef, int Mu, int Mv)
{
/* XXX need to make this also work for edge factor 0 and 1 */
int num_verts = (ef.tu0 + ef.tu1 + ef.tv0 + ef.tv1) + (Mu - 1)*(Mv - 1);
- EdgeDice::reserve(num_verts, 0);
+ int num_tris = 0;
+ EdgeDice::reserve(num_verts, num_tris);
}
float2 QuadDice::map_uv(SubPatch& sub, float u, float v)
@@ -138,8 +160,8 @@ float3 QuadDice::eval_projected(SubPatch& sub, float u, float v)
float3 P;
sub.patch->eval(&P, NULL, NULL, uv.x, uv.y);
- if(camera)
- P = transform_perspective(&camera->worldtoraster, P);
+ if(params.camera)
+ P = transform_perspective(&params.camera->worldtoraster, P);
return P;
}
@@ -222,7 +244,7 @@ float QuadDice::scale_factor(SubPatch& sub, EdgeFactors& ef, int Mu, int Mv)
float Apatch = max(A1, max(A2, max(A3, A4)))*4.0f;
/* solve for scaling factor */
- float Atri = dicing_rate*dicing_rate*0.5f;
+ float Atri = params.dicing_rate*params.dicing_rate*0.5f;
float Ntris = Apatch/Atri;
// XXX does the -sqrt solution matter
@@ -270,8 +292,8 @@ void QuadDice::add_grid(SubPatch& sub, int Mu, int Mv, int offset)
int i3 = offset + 4 + i + j*(Mu-1);
int i4 = offset + 4 + (i-1) + j*(Mu-1);
- add_triangle(i1, i2, i3);
- add_triangle(i1, i3, i4);
+ add_triangle(sub.patch, i1, i2, i3);
+ add_triangle(sub.patch, i1, i3, i4);
}
}
}
@@ -288,7 +310,7 @@ void QuadDice::dice(SubPatch& sub, EdgeFactors& ef)
Mv = max((int)ceil(S*Mv), 2); // XXX handle 0 & 1?
/* reserve space for new verts */
- int offset = mesh->verts.size();
+ int offset = params.mesh->verts.size();
reserve(ef, Mu, Mv);
/* corners and inner grid */
@@ -299,27 +321,27 @@ void QuadDice::dice(SubPatch& sub, EdgeFactors& ef)
vector<int> outer, inner;
add_side_u(sub, outer, inner, Mu, Mv, ef.tu0, 0, offset);
- stitch_triangles(outer, inner);
+ stitch_triangles(sub.patch, outer, inner);
/* top side */
add_side_u(sub, outer, inner, Mu, Mv, ef.tu1, 1, offset);
- stitch_triangles(inner, outer);
+ stitch_triangles(sub.patch, inner, outer);
/* left side */
add_side_v(sub, outer, inner, Mu, Mv, ef.tv0, 0, offset);
- stitch_triangles(inner, outer);
+ stitch_triangles(sub.patch, inner, outer);
/* right side */
add_side_v(sub, outer, inner, Mu, Mv, ef.tv1, 1, offset);
- stitch_triangles(outer, inner);
+ stitch_triangles(sub.patch, outer, inner);
- assert(vert_offset == mesh->verts.size());
+ assert(vert_offset == params.mesh->verts.size());
}
/* TriangleDice */
-TriangleDice::TriangleDice(Mesh *mesh_, int shader_, bool smooth_, float dicing_rate_)
-: EdgeDice(mesh_, shader_, smooth_, dicing_rate_)
+TriangleDice::TriangleDice(const SubdParams& params_)
+: EdgeDice(params_)
{
}
@@ -417,9 +439,9 @@ void TriangleDice::add_grid(SubPatch& sub, EdgeFactors& ef, int M)
inner_w.push_back(corner_v);
/* stitch together inner/outer with triangles */
- stitch_triangles(outer_u, inner_u);
- stitch_triangles(outer_v, inner_v);
- stitch_triangles(outer_w, inner_w);
+ stitch_triangles(sub.patch, outer_u, inner_u);
+ stitch_triangles(sub.patch, outer_v, inner_v);
+ stitch_triangles(sub.patch, outer_w, inner_w);
outer_u = inner_u;
outer_v = inner_v;
@@ -429,18 +451,18 @@ void TriangleDice::add_grid(SubPatch& sub, EdgeFactors& ef, int M)
/* fill up last part */
if(m == -1) {
/* single triangle */
- add_triangle(outer_w[0], outer_u[0], outer_v[0]);
+ add_triangle(sub.patch, outer_w[0], outer_u[0], outer_v[0]);
}
else {
/* center vertex + 6 triangles */
int center = add_vert(sub, make_float2(1.0f/3.0f, 1.0f/3.0f));
- add_triangle(outer_w[0], outer_w[1], center);
- add_triangle(outer_w[1], outer_w[2], center);
- add_triangle(outer_u[0], outer_u[1], center);
- add_triangle(outer_u[1], outer_u[2], center);
- add_triangle(outer_v[0], outer_v[1], center);
- add_triangle(outer_v[1], outer_v[2], center);
+ add_triangle(sub.patch, outer_w[0], outer_w[1], center);
+ add_triangle(sub.patch, outer_w[1], outer_w[2], center);
+ add_triangle(sub.patch, outer_u[0], outer_u[1], center);
+ add_triangle(sub.patch, outer_u[1], outer_u[2], center);
+ add_triangle(sub.patch, outer_v[0], outer_v[1], center);
+ add_triangle(sub.patch, outer_v[1], outer_v[2], center);
}
}
@@ -452,7 +474,7 @@ void TriangleDice::dice(SubPatch& sub, EdgeFactors& ef)
reserve(ef, M);
add_grid(sub, ef, M);
- assert(vert_offset == mesh->verts.size());
+ assert(vert_offset == params.mesh->verts.size());
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/subd/subd_dice.h b/intern/cycles/subd/subd_dice.h
index 250de59c6c3..9cf5b0d50b8 100644
--- a/intern/cycles/subd/subd_dice.h
+++ b/intern/cycles/subd/subd_dice.h
@@ -31,28 +31,50 @@ class Camera;
class Mesh;
class Patch;
+struct SubdParams {
+ Mesh *mesh;
+ int shader;
+ bool smooth;
+ bool ptex;
+
+ int test_steps;
+ int split_threshold;
+ float dicing_rate;
+ Camera *camera;
+
+ SubdParams(Mesh *mesh_, int shader_, bool smooth_ = true, bool ptex_ = false)
+ {
+ mesh = mesh_;
+ shader = shader_;
+ smooth = smooth_;
+ ptex = ptex_;
+
+ test_steps = 3;
+ split_threshold = 1;
+ dicing_rate = 0.1f;
+ camera = NULL;
+ }
+
+};
+
/* EdgeDice Base */
class EdgeDice {
public:
- Camera *camera;
- Mesh *mesh;
+ SubdParams params;
float3 *mesh_P;
float3 *mesh_N;
- float dicing_rate;
size_t vert_offset;
size_t tri_offset;
- int shader;
- bool smooth;
- EdgeDice(Mesh *mesh, int shader, bool smooth, float dicing_rate);
+ EdgeDice(const SubdParams& params);
void reserve(int num_verts, int num_tris);
int add_vert(Patch *patch, float2 uv);
- void add_triangle(int v0, int v1, int v2);
+ void add_triangle(Patch *patch, int v0, int v1, int v2);
- void stitch_triangles(vector<int>& outer, vector<int>& inner);
+ void stitch_triangles(Patch *patch, vector<int>& outer, vector<int>& inner);
};
/* Quad EdgeDice
@@ -86,7 +108,7 @@ public:
int tv1;
};
- QuadDice(Mesh *mesh, int shader, bool smooth, float dicing_rate);
+ QuadDice(const SubdParams& params);
void reserve(EdgeFactors& ef, int Mu, int Mv);
float3 eval_projected(SubPatch& sub, float u, float v);
@@ -140,7 +162,7 @@ public:
int tw;
};
- TriangleDice(Mesh *mesh, int shader, bool smooth, float dicing_rate);
+ TriangleDice(const SubdParams& params);
void reserve(EdgeFactors& ef, int M);
diff --git a/intern/cycles/subd/subd_edge.h b/intern/cycles/subd/subd_edge.h
deleted file mode 100644
index edf98c8a5a0..00000000000
--- a/intern/cycles/subd/subd_edge.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Original code in the public domain -- castanyo@yahoo.es
- *
- * Modifications copyright (c) 2011, Blender Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __SUBD_EDGE_H__
-#define __SUBD_EDGE_H__
-
-#include "subd_mesh.h"
-
-CCL_NAMESPACE_BEGIN
-
-/* Subd Half Edge */
-
-class SubdEdge
-{
-public:
- int id;
-
- SubdEdge *next;
- SubdEdge *prev;
- SubdEdge *pair;
- SubdVert *vert;
- SubdFace *face;
-
- SubdEdge(int id_)
- {
- id = id_;
- next = NULL;
- prev = NULL;
- pair = NULL;
- vert = NULL;
- face = NULL;
- }
-
- /* vertex queries */
- SubdVert *from() { return vert; }
- SubdVert *to() { return next->vert; }
-
- /* face queries */
- bool is_boundary() { return !(face && pair->face); }
-};
-
-CCL_NAMESPACE_END
-
-#endif /* __SUBD_EDGE_H__ */
-
diff --git a/intern/cycles/subd/subd_face.h b/intern/cycles/subd/subd_face.h
deleted file mode 100644
index 8f8a9ec3f47..00000000000
--- a/intern/cycles/subd/subd_face.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Original code in the public domain -- castanyo@yahoo.es
- *
- * Modifications copyright (c) 2011, Blender Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __SUBD_FACE_H__
-#define __SUBD_FACE_H__
-
-#include "subd_edge.h"
-#include "subd_mesh.h"
-
-CCL_NAMESPACE_BEGIN
-
-/* Subd Face */
-
-class SubdFace
-{
-public:
- int id;
- SubdEdge *edge;
-
- SubdFace(int id_)
- {
- id = id_;
- edge = NULL;
- }
-
- bool contains(SubdEdge *e)
- {
- for(EdgeIterator it(edges()); !it.isDone(); it.advance())
- if(it.current() == e)
- return true;
-
- return false;
- }
-
- int num_edges()
- {
- int num = 0;
-
- for(EdgeIterator it(edges()); !it.isDone(); it.advance())
- num++;
-
- return num;
- }
-
- bool is_boundary()
- {
- for(EdgeIterator it(edges()); !it.isDone(); it.advance()) {
- SubdEdge *edge = it.current();
-
- if(edge->pair->face == NULL)
- return true;
- }
-
- return false;
- }
-
- /* iterate over edges in clockwise order */
- class EdgeIterator
- {
- public:
- EdgeIterator(SubdEdge *e) : end(NULL), cur(e) { }
-
- virtual void advance()
- {
- if (end == NULL) end = cur;
- cur = cur->next;
- }
-
- virtual bool isDone() { return end == cur; }
- virtual SubdEdge *current() { return cur; }
-
- private:
- SubdEdge *end;
- SubdEdge *cur;
- };
-
- EdgeIterator edges() { return EdgeIterator(edge); }
- EdgeIterator edges(SubdEdge *edge) { return EdgeIterator(edge); }
-};
-
-CCL_NAMESPACE_END
-
-#endif /* __SUBD_FACE_H__ */
-
diff --git a/intern/cycles/subd/subd_mesh.cpp b/intern/cycles/subd/subd_mesh.cpp
index becd5b9b5ec..0db20656f39 100644
--- a/intern/cycles/subd/subd_mesh.cpp
+++ b/intern/cycles/subd/subd_mesh.cpp
@@ -28,282 +28,391 @@
#include <stdio.h>
-#include "subd_build.h"
-#include "subd_edge.h"
-#include "subd_face.h"
#include "subd_mesh.h"
#include "subd_patch.h"
#include "subd_split.h"
-#include "subd_vert.h"
#include "util_debug.h"
#include "util_foreach.h"
+#ifdef WITH_OPENSUBDIV
+
+#include <osd/vertex.h>
+#include <osd/mesh.h>
+#include <osd/cpuComputeController.h>
+#include <osd/cpuVertexBuffer.h>
+#include <osd/cpuEvalLimitController.h>
+#include <osd/evalLimitContext.h>
+
CCL_NAMESPACE_BEGIN
-SubdMesh::SubdMesh()
+/* typedefs */
+typedef OpenSubdiv::OsdVertex OsdVertex;
+typedef OpenSubdiv::FarMesh<OsdVertex> OsdFarMesh;
+typedef OpenSubdiv::FarMeshFactory<OsdVertex> OsdFarMeshFactory;
+typedef OpenSubdiv::HbrCatmarkSubdivision<OsdVertex> OsdHbrCatmarkSubdivision;
+typedef OpenSubdiv::HbrFace<OsdVertex> OsdHbrFace;
+typedef OpenSubdiv::HbrHalfedge<OsdVertex> OsdHbrHalfEdge;
+typedef OpenSubdiv::HbrMesh<OsdVertex> OsdHbrMesh;
+typedef OpenSubdiv::HbrVertex<OsdVertex> OsdHbrVertex;
+typedef OpenSubdiv::OsdCpuComputeContext OsdCpuComputeContext;
+typedef OpenSubdiv::OsdCpuComputeController OsdCpuComputeController;
+typedef OpenSubdiv::OsdCpuEvalLimitContext OsdCpuEvalLimitContext;
+typedef OpenSubdiv::OsdCpuEvalLimitController OsdCpuEvalLimitController;
+typedef OpenSubdiv::OsdCpuVertexBuffer OsdCpuVertexBuffer;
+typedef OpenSubdiv::OsdEvalCoords OsdEvalCoords;
+typedef OpenSubdiv::OsdVertexBufferDescriptor OsdVertexBufferDescriptor;
+
+/* OpenSubdiv Patch */
+
+class OpenSubdPatch : public Patch {
+public:
+ int face_id;
+
+ OpenSubdPatch(OsdFarMesh *farmesh, OsdCpuVertexBuffer *vbuf_base)
+ {
+ face_id = 0;
+
+ /* create buffers for evaluation */
+ vbuf_P = OsdCpuVertexBuffer::Create(3, 1);
+ vbuf_dPdu = OsdCpuVertexBuffer::Create(3, 1);
+ vbuf_dPdv = OsdCpuVertexBuffer::Create(3, 1);
+
+ P = vbuf_P->BindCpuBuffer();
+ dPdu = vbuf_dPdu->BindCpuBuffer();
+ dPdv = vbuf_dPdv->BindCpuBuffer();
+
+ /* setup evaluation context */
+ OsdVertexBufferDescriptor in_desc(0, 3, 3), out_desc(0, 3, 3); /* offset, length, stride */
+
+ evalctx = OsdCpuEvalLimitContext::Create(farmesh, false);
+ evalctx->GetVertexData().Bind(in_desc, vbuf_base, out_desc, vbuf_P, vbuf_dPdu, vbuf_dPdv);
+ }
+
+ ~OpenSubdPatch()
+ {
+ evalctx->GetVertexData().Unbind();
+
+ delete evalctx;
+ delete vbuf_P;
+ delete vbuf_dPdu;
+ delete vbuf_dPdv;
+ }
+
+ void eval(float3 *P_, float3 *dPdu_, float3 *dPdv_, float u, float v)
+ {
+ OsdEvalCoords coords;
+ coords.u = u;
+ coords.v = v;
+ coords.face = face_id;
+
+ evalctrl.EvalLimitSample<OsdCpuVertexBuffer,OsdCpuVertexBuffer>(coords, evalctx, 0);
+
+ *P_ = make_float3(P[0], P[1], P[2]);
+ if (dPdu_) *dPdu_ = make_float3(dPdv[0], dPdv[1], dPdv[2]);
+ if (dPdv_) *dPdv_ = make_float3(dPdu[0], dPdu[1], dPdu[2]);
+
+ /* optimize: skip evaluating derivatives when not needed */
+ /* todo: swapped derivatives, different winding convention? */
+ }
+
+ BoundBox bound()
+ {
+ /* not implemented */
+ BoundBox bbox = BoundBox::empty;
+ return bbox;
+ }
+
+ int ptex_face_id()
+ {
+ return face_id;
+ }
+
+protected:
+ OsdCpuEvalLimitController evalctrl;
+ OsdCpuEvalLimitContext *evalctx;
+ OsdCpuVertexBuffer *vbuf_P;
+ OsdCpuVertexBuffer *vbuf_dPdu;
+ OsdCpuVertexBuffer *vbuf_dPdv;
+ float *P;
+ float *dPdu;
+ float *dPdv;
+};
+
+/* OpenSubdiv Mesh */
+
+OpenSubdMesh::OpenSubdMesh()
{
+ /* create osd mesh */
+ static OsdHbrCatmarkSubdivision catmark;
+ OsdHbrMesh *hbrmesh = new OsdHbrMesh(&catmark);
+
+ /* initialize class */
+ num_verts = 0;
+ num_ptex_faces = 0;
+ _hbrmesh = (void*)hbrmesh;
}
-SubdMesh::~SubdMesh()
+OpenSubdMesh::~OpenSubdMesh()
{
- pair<Key, SubdEdge*> em;
-
- foreach(SubdVert *vertex, verts)
- delete vertex;
- foreach(em, edge_map)
- delete em.second;
- foreach(SubdFace *face, faces)
- delete face;
+ OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh;
- verts.clear();
- edges.clear();
- edge_map.clear();
- faces.clear();
+ if(hbrmesh)
+ delete hbrmesh;
}
-SubdVert *SubdMesh::add_vert(const float3& co)
+void OpenSubdMesh::add_vert(const float3& co)
{
- SubdVert *v = new SubdVert(verts.size());
- v->co = co;
- verts.push_back(v);
+ OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh;
- return v;
+ OsdVertex v;
+ positions.push_back(co.x);
+ positions.push_back(co.y);
+ positions.push_back(co.z);
+ hbrmesh->NewVertex(num_verts++, v);
}
-SubdFace *SubdMesh::add_face(int v0, int v1, int v2)
+void OpenSubdMesh::add_face(int v0, int v1, int v2)
{
int index[3] = {v0, v1, v2};
return add_face(index, 3);
}
-SubdFace *SubdMesh::add_face(int v0, int v1, int v2, int v3)
+void OpenSubdMesh::add_face(int v0, int v1, int v2, int v3)
{
int index[4] = {v0, v1, v2, v3};
- return add_face(index, 4);
+ add_face(index, 4);
}
-SubdFace *SubdMesh::add_face(int *index, int num)
+void OpenSubdMesh::add_face(int *index, int num)
{
- /* test non-manifold cases */
- if(!can_add_face(index, num)) {
- /* we could try to add face in opposite winding instead .. */
- fprintf(stderr, "Warning: non manifold mesh, invalid face '%lu'.\n", (unsigned long)faces.size());
- return NULL;
- }
-
- SubdFace *f = new SubdFace(faces.size());
-
- SubdEdge *first_edge = NULL;
- SubdEdge *last = NULL;
- SubdEdge *current = NULL;
-
- /* add edges */
- for(int i = 0; i < num-1; i++) {
- current = add_edge(index[i], index[i+1]);
- assert(current != NULL);
-
- current->face = f;
-
- if(last != NULL) {
- last->next = current;
- current->prev = last;
- }
- else
- first_edge = current;
-
- last = current;
- }
+ OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh;
- current = add_edge(index[num-1], index[0]);
- assert(current != NULL);
-
- current->face = f;
+#ifndef NDEBUG
+ /* sanity checks */
+ for(int j = 0; j < num; j++) {
+ OsdHbrVertex *origin = hbrmesh->GetVertex(index[j]);
+ OsdHbrVertex *destination = hbrmesh->GetVertex(index[(j+1)%num]);
+ OsdHbrHalfEdge *opposite = destination->GetEdge(origin);
- last->next = current;
- current->prev = last;
+ if(origin==NULL || destination==NULL)
+ assert("An edge was specified that connected a nonexistent vertex\n");
- current->next = first_edge;
- first_edge->prev = current;
+ if(origin == destination)
+ assert("An edge was specified that connected a vertex to itself\n");
- f->edge = first_edge;
- faces.push_back(f);
+ if(opposite && opposite->GetOpposite())
+ assert("A non-manifold edge incident to more than 2 faces was found\n");
- return f;
-}
+ if(origin->GetEdge(destination))
+ assert("An edge connecting two vertices was specified more than once."
+ "It's likely that an incident face was flipped\n");
+ }
+#endif
-bool SubdMesh::can_add_face(int *index, int num)
-{
- /* manifold check */
- for(int i = 0; i < num-1; i++)
- if(!can_add_edge(index[i], index[i+1]))
- return false;
+ OsdHbrFace *face = hbrmesh->NewFace(num, index, 0);
+
+ /* this is required for limit eval patch table? */
+ face->SetPtexIndex(num_ptex_faces);
- return can_add_edge(index[num-1], index[0]);
+ if(num == 4)
+ num_ptex_faces++;
+ else
+ num_ptex_faces += num;
}
-bool SubdMesh::can_add_edge(int i, int j)
+bool OpenSubdMesh::finish()
{
- /* check for degenerate edge */
- if(i == j)
- return false;
+ OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh;
- /* make sure edge has not been added yet. */
- return find_edge(i, j) == NULL;
-}
+ /* finish hbr mesh construction */
+ hbrmesh->SetInterpolateBoundaryMethod(OsdHbrMesh::k_InterpolateBoundaryEdgeOnly);
+ hbrmesh->Finish();
-SubdEdge *SubdMesh::add_edge(int i, int j)
-{
- SubdEdge *edge;
-
- /* find pair */
- SubdEdge *pair = find_edge(j, i);
-
- if(pair != NULL) {
- /* create edge with same id */
- edge = new SubdEdge(pair->id + 1);
-
- /* link edge pairs */
- edge->pair = pair;
- pair->pair = edge;
-
- /* not sure this is necessary? */
- pair->vert->edge = pair;
- }
- else {
- /* create edge */
- edge = new SubdEdge(2*edges.size());
-
- /* add only unpaired edges */
- edges.push_back(edge);
- }
-
- /* assign vertex and put into map */
- edge->vert = verts[i];
- edge_map[Key(i, j)] = edge;
-
- /* face and next are set by add_face */
-
- return edge;
+ return true;
}
-SubdEdge *SubdMesh::find_edge(int i, int j)
+void OpenSubdMesh::tessellate(DiagSplit *split)
{
- map<Key, SubdEdge*>::const_iterator it = edge_map.find(Key(i, j));
+ if (num_ptex_faces == 0)
+ return;
- return (it == edge_map.end())? NULL: it->second;
-}
+ const int level = 3;
+ const bool requirefvar = false;
-bool SubdMesh::link_boundary()
-{
- /* link boundary edges once the mesh has been created */
- int num = 0;
-
- /* create boundary edges */
- int num_edges = edges.size();
+ /* convert HRB to FAR mesh */
+ OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh;
- for(int e = 0; e < num_edges; e++) {
- SubdEdge *edge = edges[e];
+ OsdFarMeshFactory meshFactory(hbrmesh, level, true);
+ OsdFarMesh *farmesh = meshFactory.Create(requirefvar);
+ int num_hbr_verts = hbrmesh->GetNumVertices();
- if(edge->pair == NULL) {
- SubdEdge *pair = new SubdEdge(edge->id + 1);
+ delete hbrmesh;
+ hbrmesh = NULL;
+ _hbrmesh = NULL;
- int i = edge->from()->id;
- int j = edge->to()->id;
+ /* refine HBR mesh with vertex coordinates */
+ OsdCpuComputeController *compute_controller = new OsdCpuComputeController();
+ OsdCpuComputeContext *compute_context = OsdCpuComputeContext::Create(farmesh);
- assert(edge_map.find(Key(j, i)) == edge_map.end());
+ OsdCpuVertexBuffer *vbuf_base = OsdCpuVertexBuffer::Create(3, num_hbr_verts);
+ vbuf_base->UpdateData(&positions[0], 0, num_verts);
- pair->vert = verts[j];
- edge_map[Key(j, i)] = pair;
-
- edge->pair = pair;
- pair->pair = edge;
-
- num++;
- }
- }
+ compute_controller->Refine(compute_context, farmesh->GetKernelBatches(), vbuf_base);
+ compute_controller->Synchronize();
- /* link boundary edges */
- for(int e = 0; e < num_edges; e++) {
- SubdEdge *edge = edges[e];
+ /* split & dice patches */
+ OpenSubdPatch patch(farmesh, vbuf_base);
- if(edge->pair->face == NULL)
- link_boundary_edge(edge->pair);
+ for(int f = 0; f < num_ptex_faces; f++) {
+ patch.face_id = f;
+ split->split_quad(&patch);
}
-
- /* detect boundary intersections */
- int boundaryIntersections = 0;
- int num_verts = verts.size();
- for(int v = 0; v < num_verts; v++) {
- SubdVert *vertex = verts[v];
+ /* clean up */
+ delete farmesh;
+ delete compute_controller;
+ delete compute_context;
+ delete vbuf_base;
+}
- int boundarySubdEdges = 0;
- for(SubdVert::EdgeIterator it(vertex->edges()); !it.isDone(); it.advance())
- if(it.current()->is_boundary())
- boundarySubdEdges++;
+CCL_NAMESPACE_END
- if(boundarySubdEdges > 2) {
- assert((boundarySubdEdges & 1) == 0);
- boundaryIntersections++;
- }
+#else /* WITH_OPENSUBDIV */
+
+CCL_NAMESPACE_BEGIN
+
+/* Subd Vertex */
+
+class SubdVert
+{
+public:
+ int id;
+ float3 co;
+
+ SubdVert(int id_)
+ {
+ id = id_;
+ co = make_float3(0.0f, 0.0f, 0.0f);
}
+};
- if(boundaryIntersections != 0) {
- fprintf(stderr, "Invalid mesh, boundary intersections found!\n");
- return false;
+/* Subd Face */
+
+class SubdFace
+{
+public:
+ int id;
+ int numverts;
+ int verts[4];
+
+ SubdFace(int id_)
+ {
+ id = id_;
+ numverts = 0;
}
+};
- return true;
+/* Subd Mesh */
+
+SubdMesh::SubdMesh()
+{
}
-void SubdMesh::link_boundary_edge(SubdEdge *edge)
+SubdMesh::~SubdMesh()
{
- /* link this boundary edge. */
+ foreach(SubdVert *vertex, verts)
+ delete vertex;
+ foreach(SubdFace *face, faces)
+ delete face;
- /* make sure next pointer has not been set. */
- assert(edge->face == NULL);
- assert(edge->next == NULL);
-
- SubdEdge *next = edge;
+ verts.clear();
+ faces.clear();
+}
- while(next->pair->face != NULL) {
- /* get pair prev */
- SubdEdge *e = next->pair->next;
+SubdVert *SubdMesh::add_vert(const float3& co)
+{
+ SubdVert *v = new SubdVert(verts.size());
+ v->co = co;
+ verts.push_back(v);
- while(e->next != next->pair)
- e = e->next;
+ return v;
+}
- next = e;
- }
+SubdFace *SubdMesh::add_face(int v0, int v1, int v2)
+{
+ int index[3] = {v0, v1, v2};
+ return add_face(index, 3);
+}
- edge->next = next->pair;
- next->pair->prev = edge;
-
- /* adjust vertex edge, so that it's the boundary edge. (required for is_boundary()) */
- if(edge->vert->edge != edge)
- edge->vert->edge = edge;
+SubdFace *SubdMesh::add_face(int v0, int v1, int v2, int v3)
+{
+ int index[4] = {v0, v1, v2, v3};
+ return add_face(index, 4);
+}
+
+SubdFace *SubdMesh::add_face(int *index, int num)
+{
+ /* skip ngons */
+ if(num < 3 || num > 4)
+ return NULL;
+
+ SubdFace *f = new SubdFace(faces.size());
+
+ for(int i = 0; i < num; i++)
+ f->verts[i] = index[i];
+
+ f->numverts = num;
+ faces.push_back(f);
+
+ return f;
+}
+
+bool SubdMesh::finish()
+{
+ return true;
}
-void SubdMesh::tessellate(DiagSplit *split, bool linear, Mesh *mesh, int shader, bool smooth)
+void SubdMesh::tessellate(DiagSplit *split)
{
- SubdBuilder *builder = SubdBuilder::create(linear);
int num_faces = faces.size();
for(int f = 0; f < num_faces; f++) {
SubdFace *face = faces[f];
- Patch *patch = builder->run(face);
+ Patch *patch;
+ float3 *hull;
+
+ if(face->numverts == 3) {
+ LinearTrianglePatch *lpatch = new LinearTrianglePatch();
+ hull = lpatch->hull;
+ patch = lpatch;
+ }
+ else if(face->numverts == 4) {
+ LinearQuadPatch *lpatch = new LinearQuadPatch();
+ hull = lpatch->hull;
+ patch = lpatch;
+ }
+ else {
+ assert(0); /* n-gons should have been split already */
+ continue;
+ }
+
+ for(int i = 0; i < face->numverts; i++)
+ hull[i] = verts[face->verts[i]]->co;
+
+ if(face->numverts == 4)
+ swap(hull[2], hull[3]);
if(patch->is_triangle())
- split->split_triangle(mesh, patch, shader, smooth);
+ split->split_triangle(patch);
else
- split->split_quad(mesh, patch, shader, smooth);
+ split->split_quad(patch);
delete patch;
}
-
- delete builder;
}
CCL_NAMESPACE_END
+#endif /* WITH_OPENSUBDIV */
+
diff --git a/intern/cycles/subd/subd_mesh.h b/intern/cycles/subd/subd_mesh.h
index e4bd5f192ab..f6aefc20318 100644
--- a/intern/cycles/subd/subd_mesh.h
+++ b/intern/cycles/subd/subd_mesh.h
@@ -35,22 +35,19 @@
CCL_NAMESPACE_BEGIN
-class SubdFace;
+#ifndef WITH_OPENSUBDIV
class SubdVert;
-class SubdEdge;
+class SubdFace;
+#endif
class DiagSplit;
class Mesh;
-/* Subd Mesh, half edge based for dynamic mesh manipulation */
+/* Subd Mesh with simple linear subdivision */
class SubdMesh
{
public:
- vector<SubdVert*> verts;
- vector<SubdEdge*> edges;
- vector<SubdFace*> faces;
-
SubdMesh();
~SubdMesh();
@@ -60,28 +57,19 @@ public:
SubdFace *add_face(int v0, int v1, int v2, int v3);
SubdFace *add_face(int *index, int num);
- bool link_boundary();
- void tessellate(DiagSplit *split, bool linear,
- Mesh *mesh, int shader, bool smooth);
+ bool finish();
+ void tessellate(DiagSplit *split);
protected:
- bool can_add_face(int *index, int num);
- bool can_add_edge(int i, int j);
- SubdEdge *add_edge(int i, int j);
- SubdEdge *find_edge(int i, int j);
- void link_boundary_edge(SubdEdge *edge);
-
- struct Key {
- Key() {}
- Key(int v0, int v1) : p0(v0), p1(v1) {}
-
- bool operator<(const Key& k) const
- { return (p0 < k.p0 || (p0 == k.p0 && p1 < k.p1)); }
-
- int p0, p1;
- };
+#ifdef WITH_OPENSUBDIV
+ void *_hbrmesh;
+ vector<float> positions;
+ int num_verts, num_ptex_faces;
+#else
+ vector<SubdVert*> verts;
+ vector<SubdFace*> faces;
+#endif
- map<Key, SubdEdge *> edge_map;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/subd/subd_patch.cpp b/intern/cycles/subd/subd_patch.cpp
index 4a029277370..fe9fa791813 100644
--- a/intern/cycles/subd/subd_patch.cpp
+++ b/intern/cycles/subd/subd_patch.cpp
@@ -27,14 +27,6 @@ CCL_NAMESPACE_BEGIN
/* De Casteljau Evaluation */
-static float3 decasteljau_quadratic(float t, const float3 cp[3])
-{
- float3 d0 = cp[0] + t*(cp[1] - cp[0]);
- float3 d1 = cp[1] + t*(cp[2] - cp[1]);
-
- return d0 + t*(d1 - d0);
-}
-
static void decasteljau_cubic(float3 *P, float3 *dt, float t, const float3 cp[4])
{
float3 d0 = cp[0] + t*(cp[1] - cp[0]);
@@ -63,17 +55,6 @@ static void decasteljau_bicubic(float3 *P, float3 *du, float3 *dv, const float3
if(du) decasteljau_cubic(du, NULL, v, utn);
}
-static float3 decasteljau_tangent(const float3 cp[12], float u, float v)
-{
- float3 ucp[3];
-
- decasteljau_cubic(ucp+0, NULL, v, cp);
- decasteljau_cubic(ucp+1, NULL, v, cp+4);
- decasteljau_cubic(ucp+2, NULL, v, cp+8);
-
- return decasteljau_quadratic(u, ucp);
-}
-
/* Linear Quad Patch */
void LinearQuadPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v)
@@ -138,149 +119,5 @@ BoundBox BicubicPatch::bound()
return bbox;
}
-/* Bicubic Patch with Tangent Fields */
-
-void BicubicTangentPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v)
-{
- decasteljau_bicubic(P, NULL, NULL, hull, u, v);
-
- if(dPdu) *dPdu = decasteljau_tangent(utan, u, v);
- if(dPdv) *dPdv = decasteljau_tangent(vtan, v, u);
-}
-
-BoundBox BicubicTangentPatch::bound()
-{
- BoundBox bbox = BoundBox::empty;
-
- for(int i = 0; i < 16; i++)
- bbox.grow(hull[i]);
-
- return bbox;
-}
-
-/* Gregory Patch */
-
-static float no_zero_div(float f)
-{
- if(f == 0.0f) return 1.0f;
- return f;
-}
-
-void GregoryQuadPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v)
-{
- float3 bicubic[16];
-
- float U = 1 - u;
- float V = 1 - v;
-
- /* 8 9 10 11
- * 12 0\1 2/3 13
- * 14 4/5 6\7 15
- * 16 17 18 19
- */
-
- bicubic[5] = (u*hull[1] + v*hull[0])/no_zero_div(u + v);
- bicubic[6] = (U*hull[2] + v*hull[3])/no_zero_div(U + v);
- bicubic[9] = (u*hull[5] + V*hull[4])/no_zero_div(u + V);
- bicubic[10] = (U*hull[6] + V*hull[7])/no_zero_div(U + V);
-
- // Map gregory control points to bezier control points.
- bicubic[0] = hull[8];
- bicubic[1] = hull[9];
- bicubic[2] = hull[10];
- bicubic[3] = hull[11];
- bicubic[4] = hull[12];
- bicubic[7] = hull[13];
- bicubic[8] = hull[14];
- bicubic[11] = hull[15];
- bicubic[12] = hull[16];
- bicubic[13] = hull[17];
- bicubic[14] = hull[18];
- bicubic[15] = hull[19];
-
- decasteljau_bicubic(P, dPdu, dPdv, bicubic, u, v);
-}
-
-BoundBox GregoryQuadPatch::bound()
-{
- BoundBox bbox = BoundBox::empty;
-
- for(int i = 0; i < 20; i++)
- bbox.grow(hull[i]);
-
- return bbox;
-}
-
-void GregoryTrianglePatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v)
-{
- /* 6
- *
- * 14 0/1 7
- *
- * 13 5/4 3\2 8
- *
- * 12 11 10 9
- */
-
- float w = 1 - u - v;
- float uu = u * u;
- float vv = v * v;
- float ww = w * w;
- float uuu = uu * u;
- float vvv = vv * v;
- float www = ww * w;
-
- float U = 1 - u;
- float V = 1 - v;
- float W = 1 - w;
-
- float3 C0 = ( v*U * hull[5] + u*V * hull[4] ) / no_zero_div(v*U + u*V);
- float3 C1 = ( w*V * hull[3] + v*W * hull[2] ) / no_zero_div(w*V + v*W);
- float3 C2 = ( u*W * hull[1] + w*U * hull[0] ) / no_zero_div(u*W + w*U);
-
- *P =
- (hull[12] * www + 3*hull[11] * ww*u + 3*hull[10] * w*uu + hull[ 9]*uuu) * (w + u) +
- (hull[ 9] * uuu + 3*hull[ 8] * uu*v + 3*hull[ 7] * u*vv + hull[ 6]*vvv) * (u + v) +
- (hull[ 6] * vvv + 3*hull[14] * vv*w + 3*hull[13] * v*ww + hull[12]*www) * (v + w) -
- (hull[12] * www*w + hull[ 9] * uuu*u + hull[ 6] * vvv*v) +
- 12*(C0 * u*v*ww + C1 * uu*v*w + C2 * u*vv*w);
-
- if(dPdu || dPdv) {
- float3 E1 = (hull[12]*www + 3*hull[11]*ww*u + 3*hull[10]*w*uu + hull[ 9]*uuu);
- float3 E2 = (hull[ 9]*uuu + 3*hull[ 8]*uu*v + 3*hull[ 7]*u*vv + hull[ 6]*vvv);
- float3 E3 = (hull[ 6]*vvv + 3*hull[14]*vv*w + 3*hull[13]*v*ww + hull[12]*www);
-
- if(dPdu) {
- float3 E1u = 3*( - hull[12]*ww + hull[11]*(ww-2*u*w) + hull[10]*(2*u*w-uu) + hull[ 9]*uu);
- float3 E2u = 3*( hull[ 9]*uu + 2*hull[ 8]*u*v + hull[ 7]*vv );
- float3 E3u = 3*( - hull[14]*vv - 2*hull[13]*v*w - hull[12]*ww);
- float3 Su = 4*( -hull[12]*www + hull[9]*uuu);
- float3 Cu = 12*( C0*(ww*v-2*u*v*w) + C1*(2*u*v*w-uu*v) + C2*vv*(w-u) );
-
- *dPdu = E1u*(w+u) + (E2+E2u*(u+v)) + (E3u*(v+w)-E3) - Su + Cu;
- }
-
- if(dPdv) {
- float3 E1v = 3*(-hull[12]*ww - 2*hull[11]*w*u - hull[10]*uu );
- float3 E2v = 3*( hull[ 8]*uu + 2*hull[ 7]*u*v + hull[ 6]*vv);
- float3 E3v = 3*( hull[ 6]*vv + hull[14]*(2*w*v-vv) + hull[13]*(ww-2*w*v) - hull[12]*ww);
- float3 Sv = 4*(-hull[12]*www + hull[ 6]*vvv);
- float3 Cv = 12*(C0*(u*ww-2*u*v*w) + C1*uu*(w-v) + C2*(2*u*v*w-u*vv));
-
- *dPdv = ((E1v*(w+u)-E1) + (E2+E2v*(u+v)) + E3v*(v+w) - Sv + Cv );
- }
- }
-}
-
-BoundBox GregoryTrianglePatch::bound()
-{
- BoundBox bbox = BoundBox::empty;
-
- for(int i = 0; i < 20; i++)
- bbox.grow(hull[i]);
-
- return bbox;
-}
-
CCL_NAMESPACE_END
diff --git a/intern/cycles/subd/subd_patch.h b/intern/cycles/subd/subd_patch.h
index 7755740ea0c..48f35d78711 100644
--- a/intern/cycles/subd/subd_patch.h
+++ b/intern/cycles/subd/subd_patch.h
@@ -22,16 +22,13 @@
CCL_NAMESPACE_BEGIN
-class Mesh;
-
-/* Base */
-
class Patch {
public:
virtual ~Patch() {}
virtual void eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v) = 0;
- virtual bool is_triangle() = 0;
+ virtual bool is_triangle() { return false; }
virtual BoundBox bound() = 0;
+ virtual int ptex_face_id() { return -1; }
};
/* Linear Quad Patch */
@@ -67,39 +64,6 @@ public:
BoundBox bound();
};
-/* Bicubic Patch with Tangent Fields */
-
-class BicubicTangentPatch : public Patch {
-public:
- float3 hull[16];
- float3 utan[12];
- float3 vtan[12];
-
- void eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v);
- bool is_triangle() { return false; }
- BoundBox bound();
-};
-
-/* Gregory Patches */
-
-class GregoryQuadPatch : public Patch {
-public:
- float3 hull[20];
-
- void eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v);
- bool is_triangle() { return false; }
- BoundBox bound();
-};
-
-class GregoryTrianglePatch : public Patch {
-public:
- float3 hull[20];
-
- void eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v);
- bool is_triangle() { return true; }
- BoundBox bound();
-};
-
CCL_NAMESPACE_END
#endif /* __SUBD_PATCH_H__ */
diff --git a/intern/cycles/subd/subd_ring.cpp b/intern/cycles/subd/subd_ring.cpp
deleted file mode 100644
index 66eab02231c..00000000000
--- a/intern/cycles/subd/subd_ring.cpp
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright 2006, NVIDIA Corporation Ignacio Castano <icastano@nvidia.com>
- *
- * Modifications copyright (c) 2011, Blender Foundation.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "subd_face.h"
-#include "subd_ring.h"
-#include "subd_stencil.h"
-#include "subd_vert.h"
-
-#include "util_algorithm.h"
-#include "util_debug.h"
-#include "util_math.h"
-
-CCL_NAMESPACE_BEGIN
-
-/* Utility for sorting verts by index */
-
-class vertex_compare
-{
-public:
- const vector<int>& index;
- vertex_compare(const vector<int>& index_) : index(index_) {}
- bool operator()(int a, int b) const { return index[a] < index[b]; }
-};
-
-/* Subd Face Ring */
-
-SubdFaceRing::SubdFaceRing(SubdFace *face, SubdEdge *firstEdge)
-{
- m_face = face;
- m_firstEdge = firstEdge;
- m_num_edges = face->num_edges();
-
- assert(m_num_edges == 3 || m_num_edges == 4);
-
- initVerts();
-}
-
-int SubdFaceRing::num_verts()
-{
- return m_verts.size();
-}
-
-SubdVert *SubdFaceRing::vertexAt(int i)
-{
- return m_verts[i];
-}
-
-int SubdFaceRing::vert_index(SubdVert *vertex)
-{
- int count = this->num_verts();
-
- for(int i = 0; i < count; i++)
- if(m_verts[i] == vertex)
- return i;
-
- assert(0);
- return 0;
-}
-
-void SubdFaceRing::evaluate_stencils(float3 *P, StencilMask *mask, int num)
-{
- /* first we sort verts by id. this way verts will always be added
- * in the same order to ensure the exact same float ops happen for control
- * points of other patches, so we get water-tight patches */
- int num_verts = m_verts.size();
-
- vector<int> vmap(num_verts);
- vector<int> vertid(num_verts);
-
- for(int v = 0; v < num_verts; v++) {
- vmap[v] = v;
- vertid[v] = m_verts[v]->id;
- }
-
- sort(vmap.begin(), vmap.end(), vertex_compare(vertid));
-
- /* then evaluate the stencils */
- for(int j = 0; j < num; j++) {
- float3 p = make_float3(0.0f, 0.0f, 0.0f);
-
- for(int i = 0; i < num_verts; i++) {
- int idx = vmap[i];
- p += m_verts[idx]->co * mask[j][idx];
- }
-
- P[j] = p;
- }
-}
-
-bool SubdFaceRing::is_triangle()
-{
- return m_num_edges == 3;
-}
-
-bool SubdFaceRing::is_quad()
-{
- return m_num_edges == 4;
-}
-
-int SubdFaceRing::num_edges()
-{
- return m_num_edges;
-}
-
-bool SubdFaceRing::is_regular(SubdFace *face)
-{
- if(!is_quad(face))
- return false;
-
- for(SubdFace::EdgeIterator it(face->edges()); !it.isDone(); it.advance()) {
- SubdEdge *edge = it.current();
-
- /* regular faces don't have boundary edges */
- if(edge->is_boundary())
- return false;
-
- /* regular faces only have ordinary verts */
- if(edge->vert->valence() != 4)
- return false;
-
- /* regular faces are only adjacent to quads */
- for(SubdVert::EdgeIterator eit(edge); !eit.isDone(); eit.advance())
- if(eit.current()->face == NULL || eit.current()->face->num_edges() != 4)
- return false;
- }
-
- return true;
-}
-
-bool SubdFaceRing::is_triangle(SubdFace *face)
-{
- return face->num_edges() == 3;
-}
-bool SubdFaceRing::is_quad(SubdFace *face)
-{
- return face->num_edges() == 4;
-}
-
-bool SubdFaceRing::is_boundary(SubdFace *face)
-{
- /* note that face->is_boundary() returns a different result. That function
- * returns true when any of the *edges* are on the boundary. however, this
- * function returns true if any of the face *verts* are on the boundary. */
-
- for(SubdFace::EdgeIterator it(face->edges()); !it.isDone(); it.advance()) {
- SubdEdge *edge = it.current();
-
- if(edge->vert->is_boundary())
- return true;
- }
-
- return false;
-}
-
-void SubdFaceRing::initVerts()
-{
- m_verts.reserve(16);
-
- /* add face verts */
- for(SubdFace::EdgeIterator it(m_firstEdge); !it.isDone(); it.advance()) {
- SubdEdge *edge = it.current();
- m_verts.push_back(edge->from());
- }
-
- // @@ Add support for non manifold surfaces!
- // The fix:
- // - not all colocals should point to the same edge.
- // - multiple colocals could belong to different boundaries, make sure they point to the right one.
-
- // @@ When the face neighborhood wraps that could result in overlapping stencils.
-
- // Add surronding verts.
- for(SubdFace::EdgeIterator it(m_firstEdge); !it.isDone(); it.advance()) {
- SubdEdge *firstEdge = it.current();
-
- int i = 0;
-
- /* traverse edges around vertex */
- for(SubdVert::ReverseEdgeIterator eit(firstEdge); !eit.isDone(); eit.advance(), i++) {
- SubdEdge *edge = eit.current();
-
- assert(edge->from()->co == firstEdge->from()->co);
-
- add_vert(edge->to());
-
- if(edge->face != NULL)
- add_vert(edge->next->to());
- }
-
- assert(i == firstEdge->from()->valence());
- }
-}
-
-
-void SubdFaceRing::add_vert(SubdVert *vertex)
-{
- /* avoid having duplicate verts */
- if(!has_vert(vertex))
- m_verts.push_back(vertex);
-}
-
-bool SubdFaceRing::has_vert(SubdVert *vertex)
-{
- int num_verts = m_verts.size();
-
- for(int i = 0; i < num_verts; i++)
- if(m_verts[i]->co == vertex->co)
- return true;
-
- return false;
-}
-
-CCL_NAMESPACE_END
-
diff --git a/intern/cycles/subd/subd_ring.h b/intern/cycles/subd/subd_ring.h
deleted file mode 100644
index f25342233b0..00000000000
--- a/intern/cycles/subd/subd_ring.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2006, NVIDIA Corporation Ignacio Castano <icastano@nvidia.com>
- *
- * Modifications copyright (c) 2011, Blender Foundation.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#ifndef __SUBD_FACE_RING_H__
-#define __SUBD_FACE_RING_H__
-
-CCL_NAMESPACE_BEGIN
-
-class StencilMask;
-class SubdVert;
-class SubdEdge;
-class SubdFace;
-
-class SubdFaceRing
-{
-public:
- SubdFaceRing(SubdFace *face, SubdEdge *edge);
-
- SubdFace *face() { return m_face; }
- SubdEdge *firstEdge() { return m_firstEdge; }
-
- int num_verts();
- SubdVert *vertexAt(int i);
- int vert_index(SubdVert *vertex);
-
- void evaluate_stencils(float3 *P, StencilMask *mask, int num);
-
- bool is_triangle();
- bool is_quad();
- int num_edges();
-
- static bool is_regular(SubdFace *face);
- static bool is_triangle(SubdFace *face);
- static bool is_quad(SubdFace *face);
- static bool is_boundary(SubdFace *face);
-
-protected:
- void initVerts();
- void add_vert(SubdVert *vertex);
- bool has_vert(SubdVert *vertex);
-
-protected:
- SubdFace *m_face;
- SubdEdge *m_firstEdge;
-
- int m_num_edges;
- vector<SubdVert*> m_verts;
-};
-
-CCL_NAMESPACE_END
-
-#endif /* __SUBD_FACE_RING_H__ */
-
diff --git a/intern/cycles/subd/subd_split.cpp b/intern/cycles/subd/subd_split.cpp
index 6c1486cecca..417ecfffd49 100644
--- a/intern/cycles/subd/subd_split.cpp
+++ b/intern/cycles/subd/subd_split.cpp
@@ -29,12 +29,9 @@ CCL_NAMESPACE_BEGIN
/* DiagSplit */
-DiagSplit::DiagSplit()
+DiagSplit::DiagSplit(const SubdParams& params_)
+: params(params_)
{
- test_steps = 3;
- split_threshold = 1;
- dicing_rate = 0.1f;
- camera = NULL;
}
void DiagSplit::dispatch(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef)
@@ -54,8 +51,8 @@ float3 DiagSplit::project(Patch *patch, float2 uv)
float3 P;
patch->eval(&P, NULL, NULL, uv.x, uv.y);
- if(camera)
- P = transform_perspective(&camera->worldtoraster, P);
+ if(params.camera)
+ P = transform_perspective(&params.camera->worldtoraster, P);
return P;
}
@@ -66,8 +63,8 @@ int DiagSplit::T(Patch *patch, float2 Pstart, float2 Pend)
float Lsum = 0.0f;
float Lmax = 0.0f;
- for(int i = 0; i < test_steps; i++) {
- float t = i/(float)(test_steps-1);
+ for(int i = 0; i < params.test_steps; i++) {
+ float t = i/(float)(params.test_steps-1);
float3 P = project(patch, Pstart + t*(Pend - Pstart));
@@ -80,10 +77,10 @@ int DiagSplit::T(Patch *patch, float2 Pstart, float2 Pend)
Plast = P;
}
- int tmin = (int)ceil(Lsum/dicing_rate);
- int tmax = (int)ceil((test_steps-1)*Lmax/dicing_rate); // XXX paper says N instead of N-1, seems wrong?
+ int tmin = (int)ceil(Lsum/params.dicing_rate);
+ int tmax = (int)ceil((params.test_steps-1)*Lmax/params.dicing_rate); // XXX paper says N instead of N-1, seems wrong?
- if(tmax - tmin > split_threshold)
+ if(tmax - tmin > params.split_threshold)
return DSPLIT_NON_UNIFORM;
return tmax;
@@ -244,7 +241,7 @@ void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int de
dispatch(sub, ef);
}
-void DiagSplit::split_triangle(Mesh *mesh, Patch *patch, int shader, bool smooth)
+void DiagSplit::split_triangle(Patch *patch)
{
TriangleDice::SubPatch sub_split;
TriangleDice::EdgeFactors ef_split;
@@ -260,8 +257,7 @@ void DiagSplit::split_triangle(Mesh *mesh, Patch *patch, int shader, bool smooth
split(sub_split, ef_split);
- TriangleDice dice(mesh, shader, smooth, dicing_rate);
- dice.camera = camera;
+ TriangleDice dice(params);
for(size_t i = 0; i < subpatches_triangle.size(); i++) {
TriangleDice::SubPatch& sub = subpatches_triangle[i];
@@ -282,7 +278,7 @@ void DiagSplit::split_triangle(Mesh *mesh, Patch *patch, int shader, bool smooth
edgefactors_triangle.clear();
}
-void DiagSplit::split_quad(Mesh *mesh, Patch *patch, int shader, bool smooth)
+void DiagSplit::split_quad(Patch *patch)
{
QuadDice::SubPatch sub_split;
QuadDice::EdgeFactors ef_split;
@@ -300,8 +296,7 @@ void DiagSplit::split_quad(Mesh *mesh, Patch *patch, int shader, bool smooth)
split(sub_split, ef_split);
- QuadDice dice(mesh, shader, smooth, dicing_rate);
- dice.camera = camera;
+ QuadDice dice(params);
for(size_t i = 0; i < subpatches_quad.size(); i++) {
QuadDice::SubPatch& sub = subpatches_quad[i];
diff --git a/intern/cycles/subd/subd_split.h b/intern/cycles/subd/subd_split.h
index 9dd10f8af8f..3f9a2721977 100644
--- a/intern/cycles/subd/subd_split.h
+++ b/intern/cycles/subd/subd_split.h
@@ -41,12 +41,9 @@ public:
vector<TriangleDice::SubPatch> subpatches_triangle;
vector<TriangleDice::EdgeFactors> edgefactors_triangle;
- int test_steps;
- int split_threshold;
- float dicing_rate;
- Camera *camera;
+ SubdParams params;
- DiagSplit();
+ DiagSplit(const SubdParams& params);
float3 project(Patch *patch, float2 uv);
int T(Patch *patch, float2 Pstart, float2 Pend);
@@ -59,8 +56,8 @@ public:
void dispatch(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef);
void split(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef, int depth=0);
- void split_triangle(Mesh *mesh, Patch *patch, int shader, bool smooth);
- void split_quad(Mesh *mesh, Patch *patch, int shader, bool smooth);
+ void split_triangle(Patch *patch);
+ void split_quad(Patch *patch);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/subd/subd_stencil.cpp b/intern/cycles/subd/subd_stencil.cpp
deleted file mode 100644
index 5f76a942a59..00000000000
--- a/intern/cycles/subd/subd_stencil.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2011-2013 Blender Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-#include "subd_stencil.h"
-
-#include "util_debug.h"
-#include "util_math.h"
-
-CCL_NAMESPACE_BEGIN
-
-StencilMask::StencilMask()
-{
-}
-
-StencilMask::StencilMask(int size)
-{
- /* initialize weights to zero. */
- weights.resize(size, 0.0f);
-}
-
-void StencilMask::resize(int size)
-{
- weights.resize(size, 0.0f);
-}
-
-StencilMask& StencilMask::operator=(float value)
-{
- const int size = weights.size();
- for(int i = 0; i < size; i++)
- weights[i] = value;
-
- return *this;
-}
-
-void StencilMask::operator+=(const StencilMask& mask)
-{
- assert(mask.size() == size());
-
- const int size = weights.size();
- for(int i = 0; i < size; i++)
- weights[i] += mask.weights[i];
-}
-
-void StencilMask::operator-=(const StencilMask& mask)
-{
- assert(mask.size() == size());
-
- const int size = weights.size();
- for(int i = 0; i < size; i++)
- weights[i] -= mask.weights[i];
-}
-
-void StencilMask::operator*=(float scale)
-{
- const int size = weights.size();
-
- for(int i = 0; i < size; i++)
- weights[i] *= scale;
-}
-
-void StencilMask::operator/=(float scale)
-{
- *this *= 1.0f/scale;
-}
-
-float StencilMask::sum() const
-{
- float total = 0.0f;
- const int size = weights.size();
-
- for(int i = 0; i < size; i++)
- total += weights[i];
-
- return total;
-}
-
-bool StencilMask::is_normalized() const
-{
- return fabsf(sum() - 1.0f) < 0.0001f;
-}
-
-void StencilMask::normalize()
-{
- *this /= sum();
-}
-
-CCL_NAMESPACE_END
-
diff --git a/intern/cycles/subd/subd_stencil.h b/intern/cycles/subd/subd_stencil.h
deleted file mode 100644
index e11d8f37cd3..00000000000
--- a/intern/cycles/subd/subd_stencil.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2006, NVIDIA Corporation Ignacio Castano <icastano@nvidia.com>
- *
- * Modifications copyright (c) 2011, Blender Foundation.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#ifndef __SUBD_STENCIL__
-#define __SUBD_STENCIL__
-
-#include "util_types.h"
-#include "util_vector.h"
-
-CCL_NAMESPACE_BEGIN
-
-class StencilMask
-{
-public:
- StencilMask();
- StencilMask(int size);
-
- void resize(int size);
-
- StencilMask& operator=(float value);
-
- void operator+=(const StencilMask& mask);
- void operator-=(const StencilMask& mask);
- void operator*=(float scale);
- void operator/=(float scale);
-
- int size() const { return weights.size(); }
-
- float operator[](int i) const { return weights[i]; }
- float& operator[](int i) { return weights[i]; }
-
- float sum() const;
- bool is_normalized() const;
- void normalize();
-
-private:
- vector<float> weights;
-};
-
-CCL_NAMESPACE_END
-
-#endif /* __SUBD_STENCIL__ */
-
diff --git a/intern/cycles/subd/subd_vert.h b/intern/cycles/subd/subd_vert.h
deleted file mode 100644
index 638019547ae..00000000000
--- a/intern/cycles/subd/subd_vert.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Original code in the public domain -- castanyo@yahoo.es
- *
- * Modifications copyright (c) 2011, Blender Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __SUBD_VERTEX_H__
-#define __SUBD_VERTEX_H__
-
-#include "subd_edge.h"
-#include "subd_mesh.h"
-
-CCL_NAMESPACE_BEGIN
-
-/* Subd Vertex */
-
-class SubdVert
-{
-public:
- int id;
- float3 co;
-
- SubdEdge *edge;
- SubdVert *next;
- SubdVert *prev;
-
- SubdVert(int id_)
- {
- id = id_;
- edge = NULL;
- co = make_float3(0.0f, 0.0f, 0.0f);
-
- next = this;
- prev = this;
- }
-
- /* valence */
- int valence()
- {
- int num = 0;
-
- for(EdgeIterator it(edges()); !it.isDone(); it.advance())
- num++;
-
- return num;
- }
-
- /* edge queries */
- bool is_boundary() { return (edge && !edge->face); }
-
- /* iterator over edges in counterclockwise order */
- class EdgeIterator
- {
- public:
- EdgeIterator(SubdEdge *e) : end(NULL), cur(e) { }
-
- virtual void advance()
- {
- if(end == NULL) end = cur;
- cur = cur->pair->next;
- //cur = cur->prev->pair;
- }
-
- virtual bool isDone() { return end == cur; }
- virtual SubdEdge *current() { return cur; }
-
- private:
- SubdEdge *end;
- SubdEdge *cur;
- };
-
- /* iterator over edges in clockwise order */
- class ReverseEdgeIterator
- {
- public:
- ReverseEdgeIterator(SubdEdge *e) : end(NULL), cur(e) { }
-
- virtual void advance()
- {
- if(end == NULL) end = cur;
- cur = cur->prev->pair;
- }
-
- virtual bool isDone() { return end == cur; }
- virtual SubdEdge *current() { return cur; }
-
- private:
- SubdEdge *end;
- SubdEdge *cur;
- };
-
- EdgeIterator edges() { return EdgeIterator(edge); }
- EdgeIterator edges(SubdEdge *edge) { return EdgeIterator(edge); }
-};
-
-CCL_NAMESPACE_END
-
-#endif /* __SUBD_VERTEX_H__ */
-
diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h
index 6db532faf74..851c67b1189 100644
--- a/intern/cycles/util/util_math.h
+++ b/intern/cycles/util/util_math.h
@@ -462,7 +462,11 @@ ccl_device_inline float3 operator/=(float3& a, float f)
ccl_device_inline float dot(const float3 a, const float3 b)
{
+#if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__)
+ return _mm_cvtss_f32(_mm_dp_ps(a, b, 0x7F));
+#else
return a.x*b.x + a.y*b.y + a.z*b.z;
+#endif
}
ccl_device_inline float3 cross(const float3 a, const float3 b)
@@ -475,7 +479,11 @@ ccl_device_inline float3 cross(const float3 a, const float3 b)
ccl_device_inline float len(const float3 a)
{
+#if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__)
+ return _mm_cvtss_f32(_mm_sqrt_ss(_mm_dp_ps(a.m128, a.m128, 0x7F)));
+#else
return sqrtf(dot(a, a));
+#endif
}
ccl_device_inline float len_squared(const float3 a)
@@ -487,7 +495,12 @@ ccl_device_inline float len_squared(const float3 a)
ccl_device_inline float3 normalize(const float3 a)
{
+#if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__)
+ __m128 norm = _mm_sqrt_ps(_mm_dp_ps(a.m128, a.m128, 0x7F));
+ return _mm_div_ps(a.m128, norm);
+#else
return a/len(a);
+#endif
}
#endif
diff --git a/intern/cycles/util/util_string.cpp b/intern/cycles/util/util_string.cpp
index 53603c54da0..61a16b63351 100644
--- a/intern/cycles/util/util_string.cpp
+++ b/intern/cycles/util/util_string.cpp
@@ -86,5 +86,24 @@ void string_split(vector<string>& tokens, const string& str, const string& separ
tokens.push_back(token);
}
+bool string_endswith(const string& s, const char *end)
+{
+ size_t len = strlen(end);
+
+ if(len > s.size())
+ return 0;
+ else
+ return strncmp(s.c_str() + s.size() - len, end, len) == 0;
+}
+
+string string_strip(const string& s)
+{
+ string result = s;
+ result.erase(0, result.find_first_not_of(' '));
+ result.erase(result.find_last_not_of(' ') + 1);
+ return result;
+
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_string.h b/intern/cycles/util/util_string.h
index ee924340716..6808f085834 100644
--- a/intern/cycles/util/util_string.h
+++ b/intern/cycles/util/util_string.h
@@ -40,6 +40,8 @@ string string_printf(const char *format, ...) PRINTF_ATTRIBUTE;
bool string_iequals(const string& a, const string& b);
void string_split(vector<string>& tokens, const string& str, const string& separators = "\t ");
+bool string_endswith(const string& s, const char *end);
+string string_strip(const string& s);
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_system.cpp b/intern/cycles/util/util_system.cpp
index 345c76bdfab..79bf5fd26b7 100644
--- a/intern/cycles/util/util_system.cpp
+++ b/intern/cycles/util/util_system.cpp
@@ -101,9 +101,7 @@ string system_cpu_brand_string()
replace_string(brand, "(TM)", "");
replace_string(brand, "(R)", "");
- size_t i;
- if((i = brand.find(" ")) != string::npos)
- brand = brand.substr(0, i);
+ brand = string_strip(brand);
return brand;
}
@@ -195,6 +193,11 @@ bool system_cpu_support_sse3()
return caps.sse && caps.sse2 && caps.sse3 && caps.ssse3;
}
+bool system_cpu_support_sse41()
+{
+ CPUCapabilities& caps = system_cpu_capabilities();
+ return caps.sse && caps.sse2 && caps.sse3 && caps.ssse3 && caps.sse41;
+}
#else
bool system_cpu_support_sse2()
diff --git a/intern/cycles/util/util_system.h b/intern/cycles/util/util_system.h
index 333782c2d01..64cfa4906b3 100644
--- a/intern/cycles/util/util_system.h
+++ b/intern/cycles/util/util_system.h
@@ -26,6 +26,7 @@ string system_cpu_brand_string();
int system_cpu_bits();
bool system_cpu_support_sse2();
bool system_cpu_support_sse3();
+bool system_cpu_support_sse41();
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h
index c53d67235f6..3fa1df6ab44 100644
--- a/intern/cycles/util/util_types.h
+++ b/intern/cycles/util/util_types.h
@@ -23,6 +23,12 @@
#endif
+/* Bitness */
+
+#if defined(__ppc64__) || defined(__PPC64__) || defined(__x86_64__) || defined(__ia64__) || defined(_M_X64)
+#define __KERNEL_64_BIT__
+#endif
+
/* Qualifiers for kernel code shared by CPU and GPU */
#ifndef __KERNEL_GPU__
@@ -34,7 +40,11 @@
#if defined(_WIN32) && !defined(FREE_WINDOWS)
#define ccl_device_inline static __forceinline
+#ifdef __KERNEL_64_BIT__
#define ccl_align(...) __declspec(align(__VA_ARGS__))
+#else
+#define ccl_align(...) /* not support for function arguments (error C2719) */
+#endif
#define ccl_may_alias
#else
#define ccl_device_inline static inline __attribute__((always_inline))
@@ -47,12 +57,6 @@
#endif
-/* Bitness */
-
-#if defined(__ppc64__) || defined(__PPC64__) || defined(__x86_64__) || defined(__ia64__) || defined(_M_X64)
-#define __KERNEL_64_BIT__
-#endif
-
/* SIMD Types */
#ifndef __KERNEL_GPU__
@@ -95,6 +99,10 @@
#include <tmmintrin.h> /* SSSE 3 */
#endif
+#ifdef __KERNEL_SSE41__
+#include <smmintrin.h> /* SSE 4.1 */
+#endif
+
#else
/* MinGW64 has conflicting declarations for these SSE headers in <windows.h>.
@@ -199,7 +207,7 @@ struct ccl_align(16) int3 {
__forceinline operator const __m128i&(void) const { return m128; }
__forceinline operator __m128i&(void) { return m128; }
#else
-struct int3 {
+struct ccl_align(16) int3 {
int x, y, z, w;
#endif
@@ -219,7 +227,7 @@ struct ccl_align(16) int4 {
__forceinline operator const __m128i&(void) const { return m128; }
__forceinline operator __m128i&(void) { return m128; }
#else
-struct int4 {
+struct ccl_align(16) int4 {
int x, y, z, w;
#endif
@@ -267,7 +275,7 @@ struct ccl_align(16) float3 {
__forceinline operator const __m128&(void) const { return m128; }
__forceinline operator __m128&(void) { return m128; }
#else
-struct float3 {
+struct ccl_align(16) float3 {
float x, y, z, w;
#endif
@@ -287,7 +295,7 @@ struct ccl_align(16) float4 {
__forceinline operator const __m128&(void) const { return m128; }
__forceinline operator __m128&(void) { return m128; }
#else
-struct float4 {
+struct ccl_align(16) float4 {
float x, y, z, w;
#endif
diff --git a/intern/elbeem/intern/ntl_blenderdumper.cpp b/intern/elbeem/intern/ntl_blenderdumper.cpp
index 4efff4337a6..ec05c25004d 100644
--- a/intern/elbeem/intern/ntl_blenderdumper.cpp
+++ b/intern/elbeem/intern/ntl_blenderdumper.cpp
@@ -164,7 +164,7 @@ int ntlBlenderDumper::renderScene( void )
boutfilename << ".bobj.gz";
gzf = gzopen(boutfilename.str().c_str(), "wb1"); // wb9 is slow for large meshes!
if (!gzf) {
- errMsg("ntlBlenderDumper::renderScene","Unable to open output '"<<boutfilename<<"' ");
+ errMsg("ntlBlenderDumper::renderScene","Unable to open output '" + boutfilename.str() + "' ");
return 1; }
// dont transform velocity output, this is handled in blender
diff --git a/intern/elbeem/intern/particletracer.cpp b/intern/elbeem/intern/particletracer.cpp
index 593b582d91f..2f1f5f8efbb 100644
--- a/intern/elbeem/intern/particletracer.cpp
+++ b/intern/elbeem/intern/particletracer.cpp
@@ -233,7 +233,7 @@ void ParticleTracer::checkDumpTextPositions(double simtime) {
if(mDumpTextFile.length()>1) {
boutfilename << mDumpTextFile << ".cpart2";
} else {
- boutfilename << boutfilename <<"_particles" << ".cpart2";
+ boutfilename << "_particles" << ".cpart2";
}
debMsgStd("ParticleTracer::checkDumpTextPositions",DM_MSG,"T-Dumping: "<< this->getName() <<", particles:"<<mParts.size()<<" "<< " to "<<boutfilename.str()<<" " , 7);
diff --git a/intern/guardedalloc/intern/mmap_win.c b/intern/guardedalloc/intern/mmap_win.c
index 6f03188a579..3096c589101 100644
--- a/intern/guardedalloc/intern/mmap_win.c
+++ b/intern/guardedalloc/intern/mmap_win.c
@@ -182,14 +182,14 @@ static void mmap_addtail(volatile mmapListBase *listbase, void *vlink)
{
struct mmapLink *link = vlink;
- if (link == 0) return;
- if (listbase == 0) return;
+ if (link == NULL) return;
+ if (listbase == NULL) return;
link->next = 0;
link->prev = listbase->last;
if (listbase->last) ((struct mmapLink *)listbase->last)->next = link;
- if (listbase->first == 0) listbase->first = link;
+ if (listbase->first == NULL) listbase->first = link;
listbase->last = link;
}
@@ -197,8 +197,8 @@ static void mmap_remlink(volatile mmapListBase *listbase, void *vlink)
{
struct mmapLink *link = vlink;
- if (link == 0) return;
- if (listbase == 0) return;
+ if (link == NULL) return;
+ if (listbase == NULL) return;
if (link->next) link->next->prev = link->prev;
if (link->prev) link->prev->next = link->next;
@@ -211,8 +211,8 @@ static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr)
{
MemMap *mm;
- if (ptr == 0) return NULL;
- if (listbase == 0) return NULL;
+ if (ptr == NULL) return NULL;
+ if (listbase == NULL) return NULL;
mm = (MemMap *)listbase->first;
while (mm) {
diff --git a/intern/itasc/Armature.cpp b/intern/itasc/Armature.cpp
index e6f5fda4066..0c736566b25 100644
--- a/intern/itasc/Armature.cpp
+++ b/intern/itasc/Armature.cpp
@@ -402,7 +402,7 @@ bool Armature::finalize()
m_armlength = 0.0;
for (i=0; i<m_neffector; i++) {
length = 0.0;
- KDL::SegmentMap::const_iterator sit = m_tree.getSegment(m_effectors[i].name);
+ KDL::SegmentMap::value_type const *sit = m_tree.getSegmentPtr(m_effectors[i].name);
while (sit->first != "root") {
Frame tip = sit->second.segment.pose(m_qKdl(sit->second.q_nr));
length += tip.p.Norm();
diff --git a/intern/itasc/kdl/tree.cpp b/intern/itasc/kdl/tree.cpp
index 8776e43f5b4..a31ac79bdf5 100644
--- a/intern/itasc/kdl/tree.cpp
+++ b/intern/itasc/kdl/tree.cpp
@@ -64,7 +64,7 @@ bool Tree::addSegment(const Segment& segment, const std::string& segment_name,
return false;
pair<SegmentMap::iterator, bool> retval;
//insert new element
- TreeElement elem(segment, parent, nrOfJoints);
+ TreeElement elem(segment, *parent, nrOfJoints);
std::pair<std::string, TreeElement> val(segment_name, elem);
retval = segments.insert(val);
diff --git a/intern/itasc/kdl/tree.hpp b/intern/itasc/kdl/tree.hpp
index 82794f96b94..8f971200969 100644
--- a/intern/itasc/kdl/tree.hpp
+++ b/intern/itasc/kdl/tree.hpp
@@ -41,32 +41,28 @@ namespace KDL
{
//Forward declaration
class TreeElement;
-#if defined(__APPLE__)
-# if MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
+#if defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
typedef std::map<std::string,TreeElement> SegmentMap;
-# else
- // Eigen allocator is needed for alignment of Eigen data types
- typedef std::map<std::string,TreeElement, std::less<std::string>, Eigen::aligned_allocator<std::pair<std::string, TreeElement> > > SegmentMap;
-# endif /* MAC_OS_X_VERSION_MIN_REQUIRED */
#else
// Eigen allocator is needed for alignment of Eigen data types
typedef std::map<std::string,TreeElement, std::less<std::string>, Eigen::aligned_allocator<std::pair<std::string, TreeElement> > > SegmentMap;
#endif
+
class TreeElement
{
public:
- TreeElement():q_nr(0)
+ TreeElement():q_nr(0),parent(0)
{};
public:
Segment segment;
unsigned int q_nr;
- SegmentMap::const_iterator parent;
+ SegmentMap::value_type const *parent;
std::vector<SegmentMap::const_iterator > children;
- TreeElement(const Segment& segment_in,const SegmentMap::const_iterator& parent_in,unsigned int q_nr_in)
+ TreeElement(const Segment& segment_in,const SegmentMap::value_type& parent_in,unsigned int q_nr_in)
{
q_nr=q_nr_in;
segment=segment_in;
- parent=parent_in;
+ parent=&parent_in;
};
static TreeElement Root()
{
@@ -167,7 +163,15 @@ namespace KDL
return segments.find(segment_name);
};
+ SegmentMap::value_type const* getSegmentPtr(const std::string& segment_name)const
+ {
+ SegmentMap::const_iterator it = segments.find(segment_name);
+
+ if (it == segments.end())
+ return 0;
+ return &*it;
+ };
const SegmentMap& getSegments()const
{
diff --git a/intern/itasc/kdl/treefksolverpos_recursive.cpp b/intern/itasc/kdl/treefksolverpos_recursive.cpp
index 9103a2165bb..fd78c46f837 100644
--- a/intern/itasc/kdl/treefksolverpos_recursive.cpp
+++ b/intern/itasc/kdl/treefksolverpos_recursive.cpp
@@ -35,22 +35,22 @@ namespace KDL {
int TreeFkSolverPos_recursive::JntToCart(const JntArray& q_in, Frame& p_out, const std::string& segmentName, const std::string& baseName)
{
- SegmentMap::const_iterator it = tree.getSegment(segmentName);
- SegmentMap::const_iterator baseit = tree.getSegment(baseName);
+ SegmentMap::value_type const* it = tree.getSegmentPtr(segmentName);
+ SegmentMap::value_type const* baseit = tree.getSegmentPtr(baseName);
if(q_in.rows() != tree.getNrOfJoints())
return -1;
- else if(it == tree.getSegments().end()) //if the segment name is not found
+ else if(!it) //if the segment name is not found
return -2;
- else if(baseit == tree.getSegments().end()) //if the base segment name is not found
+ else if(!baseit) //if the base segment name is not found
return -3;
else{
- p_out = recursiveFk(q_in, it, baseit);
- return 0;
+ p_out = recursiveFk(q_in, it, baseit);
+ return 0;
}
}
- Frame TreeFkSolverPos_recursive::recursiveFk(const JntArray& q_in, const SegmentMap::const_iterator& it, const SegmentMap::const_iterator& baseit)
+ Frame TreeFkSolverPos_recursive::recursiveFk(const JntArray& q_in, SegmentMap::value_type const* it, SegmentMap::value_type const* baseit)
{
//gets the frame for the current element (segment)
const TreeElement& currentElement = it->second;
@@ -60,8 +60,7 @@ namespace KDL {
}
else{
Frame currentFrame = currentElement.segment.pose(((JntArray&)q_in)(currentElement.q_nr));
- SegmentMap::const_iterator parentIt = currentElement.parent;
- return recursiveFk(q_in, parentIt, baseit) * currentFrame;
+ return recursiveFk(q_in, currentElement.parent, baseit) * currentFrame;
}
}
diff --git a/intern/itasc/kdl/treefksolverpos_recursive.hpp b/intern/itasc/kdl/treefksolverpos_recursive.hpp
index c22fe4af75b..2081f23a9ff 100644
--- a/intern/itasc/kdl/treefksolverpos_recursive.hpp
+++ b/intern/itasc/kdl/treefksolverpos_recursive.hpp
@@ -45,7 +45,7 @@ namespace KDL {
private:
const Tree tree;
- Frame recursiveFk(const JntArray& q_in, const SegmentMap::const_iterator& it, const SegmentMap::const_iterator& baseit);
+ Frame recursiveFk(const JntArray& q_in, SegmentMap::value_type const* it, SegmentMap::value_type const* baseit);
};
}
diff --git a/intern/itasc/kdl/treejnttojacsolver.cpp b/intern/itasc/kdl/treejnttojacsolver.cpp
index 624bbef7990..e8b4d385ab2 100644
--- a/intern/itasc/kdl/treejnttojacsolver.cpp
+++ b/intern/itasc/kdl/treejnttojacsolver.cpp
@@ -28,16 +28,16 @@ int TreeJntToJacSolver::JntToJac(const JntArray& q_in, Jacobian& jac,
return -1;
//Lets search the tree-element
- SegmentMap::const_iterator it = tree.getSegments().find(segmentname);
+ SegmentMap::value_type const* it = tree.getSegmentPtr(segmentname);
//If segmentname is not inside the tree, back out:
- if (it == tree.getSegments().end())
+ if (!it)
return -2;
//Let's make the jacobian zero:
SetToZero(jac);
- SegmentMap::const_iterator root = tree.getSegments().find("root");
+ SegmentMap::value_type const* root = tree.getSegmentPtr("root");
Frame T_total = Frame::Identity();
Frame T_local, T_joint;
diff --git a/intern/locale/SConscript b/intern/locale/SConscript
index 42941e2105f..4136ac8237d 100644
--- a/intern/locale/SConscript
+++ b/intern/locale/SConscript
@@ -58,9 +58,9 @@ if env['WITH_BF_INTERNATIONAL']:
os.makedirs(build_dir)
msgfmt_tool = env.Clone()
+ msgfmt_tool.Append(LINKFLAGS = env['PLATFORM_LINKFLAGS'])
+
targetpath = root_build_dir + '/msgfmt'
- if env['OURPLATFORM'] == 'darwin':
- msgfmt_tool.Replace( LINKFLAGS = '/usr/lib/libgcc_s.1.dylib /usr/lib/libstdc++.6.dylib /usr/lib/libSystem.B.dylib') # only need these dependencies
msgfmt_target = msgfmt_tool.Program(target = targetpath, source = ['msgfmt.cc'])
diff --git a/intern/memutil/MEM_CacheLimiter.h b/intern/memutil/MEM_CacheLimiter.h
index dec4d0b1c30..32f97a21815 100644
--- a/intern/memutil/MEM_CacheLimiter.h
+++ b/intern/memutil/MEM_CacheLimiter.h
@@ -138,8 +138,8 @@ public:
typedef size_t (*MEM_CacheLimiter_DataSize_Func) (void *data);
typedef int (*MEM_CacheLimiter_ItemPriority_Func) (void *item, int default_priority);
- MEM_CacheLimiter(MEM_CacheLimiter_DataSize_Func getDataSize_)
- : getDataSize(getDataSize_) {
+ MEM_CacheLimiter(MEM_CacheLimiter_DataSize_Func data_size_func)
+ : data_size_func(data_size_func) {
}
~MEM_CacheLimiter() {
@@ -162,10 +162,16 @@ public:
}
size_t get_memory_in_use() {
- if (getDataSize)
- return total_size();
- else
- return MEM_get_memory_in_use();
+ size_t size = 0;
+ if (data_size_func) {
+ for (iterator it = queue.begin(); it != queue.end(); it++) {
+ size += data_size_func((*it)->get()->get_data());
+ }
+ }
+ else {
+ size = MEM_get_memory_in_use();
+ }
+ return size;
}
void enforce_limits() {
@@ -188,15 +194,15 @@ public:
if (!elem)
break;
- if (getDataSize) {
- cur_size = getDataSize(elem->get()->get_data());
+ if (data_size_func) {
+ cur_size = data_size_func(elem->get()->get_data());
}
else {
cur_size = mem_in_use;
}
if (elem->destroy_if_possible()) {
- if (getDataSize) {
+ if (data_size_func) {
mem_in_use -= cur_size;
}
else {
@@ -207,15 +213,21 @@ public:
}
void touch(MEM_CacheLimiterHandle<T> * handle) {
- queue.push_back(handle);
- queue.erase(handle->me);
- iterator it = queue.end();
- --it;
- handle->me = it;
+ /* If we're using custom priority callback re-arranging the queue
+ * doesn't make much sense because we'll iterate it all to get
+ * least priority element anyway.
+ */
+ if (item_priority_func == NULL) {
+ queue.push_back(handle);
+ queue.erase(handle->me);
+ iterator it = queue.end();
+ --it;
+ handle->me = it;
+ }
}
void set_item_priority_func(MEM_CacheLimiter_ItemPriority_Func item_priority_func) {
- getItemPriority = item_priority_func;
+ this->item_priority_func = item_priority_func;
}
private:
@@ -223,41 +235,42 @@ private:
typedef std::list<MEM_CacheElementPtr, MEM_Allocator<MEM_CacheElementPtr> > MEM_CacheQueue;
typedef typename MEM_CacheQueue::iterator iterator;
- size_t total_size() {
- size_t size = 0;
- for (iterator it = queue.begin(); it != queue.end(); it++) {
- size+= getDataSize((*it)->get()->get_data());
- }
- return size;
- }
-
MEM_CacheElementPtr get_least_priority_destroyable_element(void) {
if (queue.empty())
return NULL;
- if (!getItemPriority)
- return *queue.begin();
-
MEM_CacheElementPtr best_match_elem = NULL;
- int best_match_priority = 0;
- iterator it;
- int i;
-
- for (it = queue.begin(), i = 0; it != queue.end(); it++, i++) {
- MEM_CacheElementPtr elem = *it;
-
- if (!elem->can_destroy())
- continue;
- /* by default 0 means highest priority element */
- /* casting a size type to int is questionable,
- but unlikely to cause problems */
- int priority = -((int)(queue.size()) - i - 1);
- priority = getItemPriority(elem->get()->get_data(), priority);
-
- if (priority < best_match_priority || best_match_elem == NULL) {
- best_match_priority = priority;
+ if (!item_priority_func) {
+ for (iterator it = queue.begin(); it != queue.end(); it++) {
+ MEM_CacheElementPtr elem = *it;
+ if (!elem->can_destroy())
+ continue;
best_match_elem = elem;
+ break;
+ }
+ }
+ else {
+ int best_match_priority = 0;
+ iterator it;
+ int i;
+
+ for (it = queue.begin(), i = 0; it != queue.end(); it++, i++) {
+ MEM_CacheElementPtr elem = *it;
+
+ if (!elem->can_destroy())
+ continue;
+
+ /* by default 0 means highest priority element */
+ /* casting a size type to int is questionable,
+ but unlikely to cause problems */
+ int priority = -((int)(queue.size()) - i - 1);
+ priority = item_priority_func(elem->get()->get_data(), priority);
+
+ if (priority < best_match_priority || best_match_elem == NULL) {
+ best_match_priority = priority;
+ best_match_elem = elem;
+ }
}
}
@@ -265,8 +278,8 @@ private:
}
MEM_CacheQueue queue;
- MEM_CacheLimiter_DataSize_Func getDataSize;
- MEM_CacheLimiter_ItemPriority_Func getItemPriority;
+ MEM_CacheLimiter_DataSize_Func data_size_func;
+ MEM_CacheLimiter_ItemPriority_Func item_priority_func;
};
-#endif // __MEM_CACHELIMITER_H__
+#endif // __MEM_CACHELIMITER_H__
diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc
index ca999eab569..6383bbbb07f 100644
--- a/intern/opencolorio/fallback_impl.cc
+++ b/intern/opencolorio/fallback_impl.cc
@@ -431,3 +431,13 @@ void FallbackImpl::finishGLSLDraw(OCIO_GLSLDrawState * /*state*/)
void FallbackImpl::freeGLState(struct OCIO_GLSLDrawState * /*state_r*/)
{
}
+
+const char *FallbackImpl::getVersionString(void)
+{
+ return "fallback";
+}
+
+int FallbackImpl::getVersionHex(void)
+{
+ return 0;
+}
diff --git a/intern/opencolorio/ocio_capi.cc b/intern/opencolorio/ocio_capi.cc
index 30668dff245..47ee3afddfd 100644
--- a/intern/opencolorio/ocio_capi.cc
+++ b/intern/opencolorio/ocio_capi.cc
@@ -338,3 +338,13 @@ void OCIO_freeOGLState(struct OCIO_GLSLDrawState *state)
{
impl->freeGLState(state);
}
+
+const char *OCIO_getVersionString(void)
+{
+ return impl->getVersionString();
+}
+
+int OCIO_getVersionHex(void)
+{
+ return impl->getVersionHex();
+}
diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h
index 5532ade1f3a..5abe104fcd4 100644
--- a/intern/opencolorio/ocio_capi.h
+++ b/intern/opencolorio/ocio_capi.h
@@ -193,6 +193,9 @@ int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorR
void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state);
void OCIO_freeOGLState(struct OCIO_GLSLDrawState *state);
+const char *OCIO_getVersionString(void);
+int OCIO_getVersionHex(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/intern/opencolorio/ocio_impl.cc b/intern/opencolorio/ocio_impl.cc
index 2cffe1a89ef..663ca2d1c75 100644
--- a/intern/opencolorio/ocio_impl.cc
+++ b/intern/opencolorio/ocio_impl.cc
@@ -609,3 +609,13 @@ void OCIOImpl::matrixTransformScale(float *m44, float *offset4, const float *sca
{
MatrixTransform::Scale(m44, offset4, scale4f);
}
+
+const char *OCIOImpl::getVersionString(void)
+{
+ return GetVersion();
+}
+
+int OCIOImpl::getVersionHex(void)
+{
+ return GetVersionHex();
+}
diff --git a/intern/opencolorio/ocio_impl.h b/intern/opencolorio/ocio_impl.h
index 8b666e8ae14..4e7c1bcc832 100644
--- a/intern/opencolorio/ocio_impl.h
+++ b/intern/opencolorio/ocio_impl.h
@@ -110,6 +110,9 @@ public:
OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide) = 0;
virtual void finishGLSLDraw(struct OCIO_GLSLDrawState *state) = 0;
virtual void freeGLState(struct OCIO_GLSLDrawState *state_r) = 0;
+
+ virtual const char *getVersionString(void) = 0;
+ virtual int getVersionHex(void) = 0;
};
class FallbackImpl : public IOCIOImpl {
@@ -194,6 +197,9 @@ public:
OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide);
void finishGLSLDraw(struct OCIO_GLSLDrawState *state);
void freeGLState(struct OCIO_GLSLDrawState *state_r);
+
+ const char *getVersionString(void);
+ int getVersionHex(void);
};
#ifdef WITH_OCIO
@@ -279,6 +285,9 @@ public:
OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide);
void finishGLSLDraw(struct OCIO_GLSLDrawState *state);
void freeGLState(struct OCIO_GLSLDrawState *state_r);
+
+ const char *getVersionString(void);
+ int getVersionHex(void);
};
#endif