Merged changes in the trunk up to revision 43038.

Conflicts resolved:
source/blender/makesdna/DNA_material_types.h
source/blenderplayer/bad_level_call_stubs/stubs.c
This commit is contained in:
Tamito Kajiyama 2011-12-31 21:09:26 +00:00
commit cc3adc2202
273 changed files with 22999 additions and 10038 deletions

@ -169,6 +169,7 @@ option(WITH_MOD_FLUID "Enable Elbeem Modifier (Fluid Simulation)" ON)
option(WITH_MOD_SMOKE "Enable Smoke Modifier (Smoke Simulation)" ON) option(WITH_MOD_SMOKE "Enable Smoke Modifier (Smoke Simulation)" ON)
option(WITH_MOD_DECIMATE "Enable Decimate Modifier" ON) option(WITH_MOD_DECIMATE "Enable Decimate Modifier" ON)
option(WITH_MOD_BOOLEAN "Enable Boolean Modifier" ON) option(WITH_MOD_BOOLEAN "Enable Boolean Modifier" ON)
option(WITH_MOD_REMESH "Enable Remesh Modifier" ON)
option(WITH_MOD_CLOTH_ELTOPO "Enable Experemental cloth solver" OFF) option(WITH_MOD_CLOTH_ELTOPO "Enable Experemental cloth solver" OFF)
mark_as_advanced(WITH_MOD_CLOTH_ELTOPO) mark_as_advanced(WITH_MOD_CLOTH_ELTOPO)
option(WITH_MOD_OCEANSIM "Enable Ocean Modifier" OFF) option(WITH_MOD_OCEANSIM "Enable Ocean Modifier" OFF)
@ -766,21 +767,26 @@ elseif(WIN32)
${LIBDIR}/opencollada/include/GeneratedSaxParser/include ${LIBDIR}/opencollada/include/GeneratedSaxParser/include
) )
set_lib_path(OPENCOLLADA_LIBPATH "opencollada/lib")
set(OPENCOLLADA_LIBRARIES set(OPENCOLLADA_LIBRARIES
${LIBDIR}/opencollada/lib/OpenCOLLADASaxFrameworkLoader.lib ${OPENCOLLADA_LIBPATH}/OpenCOLLADASaxFrameworkLoader.lib
${LIBDIR}/opencollada/lib/OpenCOLLADAFramework.lib ${OPENCOLLADA_LIBPATH}/OpenCOLLADAFramework.lib
${LIBDIR}/opencollada/lib/OpenCOLLADABaseUtils.lib ${OPENCOLLADA_LIBPATH}/OpenCOLLADABaseUtils.lib
${LIBDIR}/opencollada/lib/OpenCOLLADAStreamWriter.lib ${OPENCOLLADA_LIBPATH}/OpenCOLLADAStreamWriter.lib
${LIBDIR}/opencollada/lib/MathMLSolver.lib ${OPENCOLLADA_LIBPATH}/MathMLSolver.lib
${LIBDIR}/opencollada/lib/GeneratedSaxParser.lib ${OPENCOLLADA_LIBPATH}/GeneratedSaxParser.lib
${LIBDIR}/opencollada/lib/xml2.lib ${OPENCOLLADA_LIBPATH}/xml2.lib
${LIBDIR}/opencollada/lib/buffer.lib ${OPENCOLLADA_LIBPATH}/buffer.lib
${LIBDIR}/opencollada/lib/ftoa.lib ${OPENCOLLADA_LIBPATH}/ftoa.lib
${LIBDIR}/opencollada/lib/UTF.lib ${OPENCOLLADA_LIBPATH}/UTF.lib
) )
set(PCRE_LIBRARIES set(PCRE_LIBRARIES
${LIBDIR}/opencollada/lib/pcre.lib ${OPENCOLLADA_LIBPATH}/pcre.lib
) )
unset(OPENCOLLADA_LIBPATH)
endif() endif()
if(WITH_CODEC_FFMPEG) if(WITH_CODEC_FFMPEG)
@ -798,18 +804,8 @@ elseif(WIN32)
endif() endif()
if(WITH_IMAGE_OPENEXR) if(WITH_IMAGE_OPENEXR)
if(MSVC90) set_lib_path(OPENEXR "openexr")
set(MSVC_LIB _vs2008) set_lib_path(OPENEXR_LIBPATH "openexr/lib")
set(MSVC_INC)
elseif(MSVC10)
set(MSVC_LIB _vs2010)
set(MSVC_INC _vs2010)
else()
set(MSVC_LIB msvc)
set(MSVC_INC)
endif()
set(OPENEXR ${LIBDIR}/openexr)
set(OPENEXR_LIBPATH ${OPENEXR}/lib${MSVC_LIB})
set(OPENEXR_LIBRARIES set(OPENEXR_LIBRARIES
${OPENEXR_LIBPATH}/Iex.lib ${OPENEXR_LIBPATH}/Iex.lib
${OPENEXR_LIBPATH}/Half.lib ${OPENEXR_LIBPATH}/Half.lib
@ -817,7 +813,7 @@ elseif(WIN32)
${OPENEXR_LIBPATH}/Imath.lib ${OPENEXR_LIBPATH}/Imath.lib
${OPENEXR_LIBPATH}/IlmThread.lib ${OPENEXR_LIBPATH}/IlmThread.lib
) )
set(OPENEXR_INCUDE ${OPENEXR}/include${MSVC_INC}) set_lib_path(OPENEXR_INCUDE "openexr/include")
set(OPENEXR_INCLUDE_DIRS set(OPENEXR_INCLUDE_DIRS
${OPENEXR_INCUDE} ${OPENEXR_INCUDE}
${OPENEXR_INCUDE}/IlmImf ${OPENEXR_INCUDE}/IlmImf
@ -844,8 +840,8 @@ elseif(WIN32)
if(WITH_PYTHON) if(WITH_PYTHON)
# normally cached but not since we include them with blender # normally cached but not since we include them with blender
set(PYTHON_VERSION 3.2) # CACHE STRING) set(PYTHON_VERSION 3.2) # CACHE STRING)
set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}") # CACHE PATH) set_lib_path(PYTHON_INCLUDE_DIR "python/include/python${PYTHON_VERSION}")
set(PYTHON_LIBRARY "${LIBDIR}/python/lib/python32.lib") #CACHE FILEPATH) set_lib_path(PYTHON_LIBRARY "python/lib/python32.lib") #CACHE FILEPATH)
# uncached vars # uncached vars
set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}") set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}")
@ -879,7 +875,7 @@ elseif(WIN32)
set(OPENIMAGEIO ${LIBDIR}/openimageio) set(OPENIMAGEIO ${LIBDIR}/openimageio)
set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include) set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include)
set(OPENIMAGEIO_LIBRARIES OpenImageIO) set(OPENIMAGEIO_LIBRARIES OpenImageIO)
set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib) set_lib_path(OPENIMAGEIO_LIBPATH "openimageio/lib")
set(OPENIMAGEIO_DEFINITIONS) set(OPENIMAGEIO_DEFINITIONS)
endif() endif()
@ -1431,11 +1427,9 @@ endif()
if(MSVC10) if(MSVC10)
if(WITH_IMAGE_OPENEXR) if(WITH_IMAGE_OPENEXR)
message(WARNING "MSVC 2010 does not support OpenEXR, disabling WITH_IMAGE_OPENEXR. To enable support use Use MSVC 2008") message(WARNING "MSVC 2010 does not support OpenEXR, disabling WITH_IMAGE_OPENEXR. To enable support use Use MSVC 2008")
set(WITH_IMAGE_OPENEXR OFF)
endif() endif()
if(WITH_OPENCOLLADA) if(WITH_OPENCOLLADA)
message(WARNING "MSVC 2010 does not support OpenCollada, disabling WITH_OPENCOLLADA. To enable support use Use MSVC 2008") message(WARNING "MSVC 2010 does not support OpenCollada, disabling WITH_OPENCOLLADA. To enable support use Use MSVC 2008")
set(WITH_OPENCOLLADA OFF)
endif() endif()
endif() endif()
@ -1577,6 +1571,7 @@ if(FIRST_RUN)
info_cfg_text("Modifiers:") info_cfg_text("Modifiers:")
info_cfg_option(WITH_MOD_BOOLEAN) info_cfg_option(WITH_MOD_BOOLEAN)
info_cfg_option(WITH_MOD_REMESH)
info_cfg_option(WITH_MOD_DECIMATE) info_cfg_option(WITH_MOD_DECIMATE)
info_cfg_option(WITH_MOD_FLUID) info_cfg_option(WITH_MOD_FLUID)
info_cfg_option(WITH_MOD_OCEANSIM) info_cfg_option(WITH_MOD_OCEANSIM)

@ -264,6 +264,7 @@ if 'blenderlite' in B.targets:
target_env_defs['WITH_BF_OCEANSIM'] = False target_env_defs['WITH_BF_OCEANSIM'] = False
target_env_defs['WITH_BF_DECIMATE'] = False target_env_defs['WITH_BF_DECIMATE'] = False
target_env_defs['WITH_BF_BOOLEAN'] = False target_env_defs['WITH_BF_BOOLEAN'] = False
target_env_defs['WITH_BF_REMESH'] = False
target_env_defs['WITH_BF_PYTHON'] = False target_env_defs['WITH_BF_PYTHON'] = False
target_env_defs['WITH_BF_3DMOUSE'] = False target_env_defs['WITH_BF_3DMOUSE'] = False

@ -665,3 +665,16 @@ function(delayed_do_install
endif() endif()
endfunction() endfunction()
macro(set_lib_path
lvar
lproj)
if(MSVC10 AND EXISTS ${LIBDIR}/vc2010/${lproj})
set(${lvar} ${LIBDIR}/vc2010/${lproj})
else()
set(${lvar} ${LIBDIR}/${lproj})
endif()
endmacro()

@ -156,15 +156,15 @@ WITH_BF_CYCLES = True
WITH_BF_OIIO = True WITH_BF_OIIO = True
BF_OIIO = LIBDIR + '/gcc/openimageio' BF_OIIO = LIBDIR + '/gcc/openimageio'
BF_OIIO_INC = '#../lib/windows/gcc/openimageio/include' BF_OIIO_INC = BF_OIIO + '/include'
BF_OIIO_LIB = 'OpenImageIO' BF_OIIO_LIB = 'OpenImageIO'
BF_OIIO_LIBPATH = '#../lib/windows/gcc/openimageio/lib' BF_OIIO_LIBPATH = BF_OIIO + '/lib'
WITH_BF_BOOST = True WITH_BF_BOOST = True
BF_BOOST = LIBDIR + '/boost' BF_BOOST = LIBDIR + '/boost'
BF_BOOST_INC = '#../lib/windows/boost/include' BF_BOOST_INC = BF_BOOST + '/include'
BF_BOOST_LIB = 'boost_date_time-mgw45-mt-s-1_47 boost_filesystem-mgw45-mt-s-1_47 boost_regex-mgw45-mt-s-1_47 boost_system-mgw45-mt-s-1_47 boost_thread-mgw45-mt-s-1_47' BF_BOOST_LIB = 'boost_date_time-mgw45-mt-s-1_47 boost_filesystem-mgw45-mt-s-1_47 boost_regex-mgw45-mt-s-1_47 boost_system-mgw45-mt-s-1_47 boost_thread-mgw45-mt-s-1_47'
BF_BOOST_LIBPATH = '#../lib/windows/boost/lib/gcc' BF_BOOST_LIBPATH = BF_BOOST + '/lib/gcc'
#Ray trace optimization #Ray trace optimization
WITH_BF_RAYOPTIMIZATION = True WITH_BF_RAYOPTIMIZATION = True

@ -152,6 +152,7 @@ def validate_arguments(args, bc):
'WITH_BF_FLUID', 'WITH_BF_FLUID',
'WITH_BF_DECIMATE', 'WITH_BF_DECIMATE',
'WITH_BF_BOOLEAN', 'WITH_BF_BOOLEAN',
'WITH_BF_REMESH',
'WITH_BF_OCEANSIM', 'WITH_BF_OCEANSIM',
'WITH_BF_CXX_GUARDEDALLOC', 'WITH_BF_CXX_GUARDEDALLOC',
'WITH_BF_JEMALLOC', 'WITH_BF_STATICJEMALLOC', 'BF_JEMALLOC', 'BF_JEMALLOC_INC', 'BF_JEMALLOC_LIBPATH', 'BF_JEMALLOC_LIB', 'BF_JEMALLOC_LIB_STATIC', 'WITH_BF_JEMALLOC', 'WITH_BF_STATICJEMALLOC', 'BF_JEMALLOC', 'BF_JEMALLOC_INC', 'BF_JEMALLOC_LIBPATH', 'BF_JEMALLOC_LIB', 'BF_JEMALLOC_LIB_STATIC',
@ -261,6 +262,7 @@ def read_opts(env, cfg, args):
(BoolVariable('WITH_BF_FLUID', 'Build with Fluid simulation (Elbeem)', True)), (BoolVariable('WITH_BF_FLUID', 'Build with Fluid simulation (Elbeem)', True)),
(BoolVariable('WITH_BF_DECIMATE', 'Build with decimate modifier', True)), (BoolVariable('WITH_BF_DECIMATE', 'Build with decimate modifier', True)),
(BoolVariable('WITH_BF_BOOLEAN', 'Build with boolean modifier', True)), (BoolVariable('WITH_BF_BOOLEAN', 'Build with boolean modifier', True)),
(BoolVariable('WITH_BF_REMESH', 'Build with remesh modifier', True)),
(BoolVariable('WITH_BF_OCEANSIM', 'Build with ocean simulation', False)), (BoolVariable('WITH_BF_OCEANSIM', 'Build with ocean simulation', False)),
('BF_PROFILE_FLAGS', 'Profiling compiler flags', ''), ('BF_PROFILE_FLAGS', 'Profiling compiler flags', ''),
(BoolVariable('WITH_BF_OPENAL', 'Use OpenAL if true', False)), (BoolVariable('WITH_BF_OPENAL', 'Use OpenAL if true', False)),

@ -45,7 +45,7 @@ if(WITH_BUILTIN_GLEW)
endif() endif()
if(WITH_GAMEENGINE) if(WITH_GAMEENGINE)
add_subdirectory(recastnavigation) add_subdirectory(recastnavigation)
endif() endif()
if(WITH_IMAGE_OPENJPEG AND (NOT UNIX OR APPLE)) if(WITH_IMAGE_OPENJPEG AND (NOT UNIX OR APPLE))

@ -36,6 +36,10 @@ if(WITH_AUDASPACE)
add_subdirectory(audaspace) add_subdirectory(audaspace)
endif() endif()
if(WITH_MOD_REMESH)
add_subdirectory(dualcon)
endif()
if(WITH_MOD_FLUID) if(WITH_MOD_FLUID)
add_subdirectory(elbeem) add_subdirectory(elbeem)
endif() endif()

@ -22,6 +22,9 @@ SConscript(['audaspace/SConscript',
# perhaps get rid of intern/csg? # perhaps get rid of intern/csg?
NEW_CSG='false' NEW_CSG='false'
if env ['WITH_BF_REMESH']:
SConscript(['dualcon/SConscript'])
if env['WITH_BF_FLUID']: if env['WITH_BF_FLUID']:
SConscript(['elbeem/SConscript']) SConscript(['elbeem/SConscript'])

@ -36,19 +36,19 @@ if(WITH_CYCLES_OPTIMIZED_KERNEL)
endif() endif()
if(WITH_CYCLES_NETWORK) if(WITH_CYCLES_NETWORK)
add_definitions(-DWITH_NETWORK) add_definitions(-DWITH_NETWORK)
endif() endif()
if(WITH_CYCLES_OSL) if(WITH_CYCLES_OSL)
add_definitions(-DWITH_OSL) add_definitions(-DWITH_OSL)
endif() endif()
if(WITH_CYCLES_PARTIO) if(WITH_CYCLES_PARTIO)
add_definitions(-DWITH_PARTIO) add_definitions(-DWITH_PARTIO)
endif() endif()
if(WITH_CYCLES_CUDA_BINARIES) if(WITH_CYCLES_CUDA_BINARIES)
add_definitions(-DWITH_CUDA_BINARIES) add_definitions(-DWITH_CUDA_BINARIES)
endif() endif()
add_definitions(-DWITH_OPENCL) add_definitions(-DWITH_OPENCL)

@ -72,17 +72,12 @@ static float blender_camera_focal_distance(BL::Object b_ob, BL::Camera b_camera)
if(!b_dof_object) if(!b_dof_object)
return b_camera.dof_distance(); return b_camera.dof_distance();
/* for dof object, return distance along camera direction. this is /* for dof object, return distance along camera Z direction */
* compatible with blender, but does it fit our dof model? */ Transform obmat = transform_clear_scale(get_transform(b_ob.matrix_world()));
Transform obmat = get_transform(b_ob.matrix_world());
Transform dofmat = get_transform(b_dof_object.matrix_world()); Transform dofmat = get_transform(b_dof_object.matrix_world());
Transform mat = transform_inverse(obmat) * dofmat;
float3 cam_p = transform_get_column(&obmat, 3); return fabsf(transform_get_column(&mat, 3).z);
float3 cam_dir = normalize(transform_get_column(&obmat, 2));
float3 dof_p = transform_get_column(&dofmat, 3);
float3 proj_p = dot(dof_p, cam_dir) * cam_dir;
return len(proj_p - cam_p);
} }
static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob) static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob)

@ -597,10 +597,14 @@ static void add_nodes(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNodeTr
else else
to_pair = sockets_map[b_to_sock.ptr.data]; to_pair = sockets_map[b_to_sock.ptr.data];
ShaderOutput *output = from_pair.first->output(from_pair.second.c_str()); /* either node may be NULL when the node was not exported, typically
ShaderInput *input = to_pair.first->input(to_pair.second.c_str()); because the node type is not supported */
if(from_pair.first && to_pair.first) {
ShaderOutput *output = from_pair.first->output(from_pair.second.c_str());
ShaderInput *input = to_pair.first->input(to_pair.second.c_str());
graph->connect(output, input); graph->connect(output, input);
}
} }
} }

@ -38,7 +38,8 @@ CCL_NAMESPACE_BEGIN
DeviceTask::DeviceTask(Type type_) DeviceTask::DeviceTask(Type type_)
: type(type_), x(0), y(0), w(0), h(0), rng_state(0), rgba(0), buffer(0), : type(type_), x(0), y(0), w(0), h(0), rng_state(0), rgba(0), buffer(0),
sample(0), resolution(0), sample(0), resolution(0),
displace_input(0), displace_offset(0), displace_x(0), displace_w(0) shader_input(0), shader_output(0),
shader_eval_type(0), shader_x(0), shader_w(0)
{ {
} }
@ -46,8 +47,8 @@ void DeviceTask::split_max_size(list<DeviceTask>& tasks, int max_size)
{ {
int num; int num;
if(type == DISPLACE) { if(type == SHADER) {
num = (displace_w + max_size - 1)/max_size; num = (shader_w + max_size - 1)/max_size;
} }
else { else {
max_size = max(1, max_size/w); max_size = max(1, max_size/w);
@ -68,17 +69,17 @@ void DeviceTask::split(ThreadQueue<DeviceTask>& queue, int num)
void DeviceTask::split(list<DeviceTask>& tasks, int num) void DeviceTask::split(list<DeviceTask>& tasks, int num)
{ {
if(type == DISPLACE) { if(type == SHADER) {
num = min(displace_w, num); num = min(shader_w, num);
for(int i = 0; i < num; i++) { for(int i = 0; i < num; i++) {
int tx = displace_x + (displace_w/num)*i; int tx = shader_x + (shader_w/num)*i;
int tw = (i == num-1)? displace_w - i*(displace_w/num): displace_w/num; int tw = (i == num-1)? shader_w - i*(shader_w/num): shader_w/num;
DeviceTask task = *this; DeviceTask task = *this;
task.displace_x = tx; task.shader_x = tx;
task.displace_w = tw; task.shader_w = tw;
tasks.push_back(task); tasks.push_back(task);
} }

@ -52,7 +52,7 @@ enum MemoryType {
class DeviceTask { class DeviceTask {
public: public:
typedef enum { PATH_TRACE, TONEMAP, DISPLACE } Type; typedef enum { PATH_TRACE, TONEMAP, SHADER } Type;
Type type; Type type;
int x, y, w, h; int x, y, w, h;
@ -63,9 +63,10 @@ public:
int resolution; int resolution;
int offset, stride; int offset, stride;
device_ptr displace_input; device_ptr shader_input;
device_ptr displace_offset; device_ptr shader_output;
int displace_x, displace_w; int shader_eval_type;
int shader_x, shader_w;
DeviceTask(Type type = PATH_TRACE); DeviceTask(Type type = PATH_TRACE);

@ -141,8 +141,8 @@ public:
thread_path_trace(task); thread_path_trace(task);
else if(task.type == DeviceTask::TONEMAP) else if(task.type == DeviceTask::TONEMAP)
thread_tonemap(task); thread_tonemap(task);
else if(task.type == DeviceTask::DISPLACE) else if(task.type == DeviceTask::SHADER)
thread_displace(task); thread_shader(task);
tasks.worker_done(); tasks.worker_done();
} }
@ -207,7 +207,7 @@ public:
} }
} }
void thread_displace(DeviceTask& task) void thread_shader(DeviceTask& task)
{ {
#ifdef WITH_OSL #ifdef WITH_OSL
if(kernel_osl_use(kg)) if(kernel_osl_use(kg))
@ -216,8 +216,8 @@ public:
#ifdef WITH_OPTIMIZED_KERNEL #ifdef WITH_OPTIMIZED_KERNEL
if(system_cpu_support_optimized()) { if(system_cpu_support_optimized()) {
for(int x = task.displace_x; x < task.displace_x + task.displace_w; x++) { for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) {
kernel_cpu_optimized_displace(kg, (uint4*)task.displace_input, (float3*)task.displace_offset, x); kernel_cpu_optimized_shader(kg, (uint4*)task.shader_input, (float3*)task.shader_output, task.shader_eval_type, x);
if(tasks.worker_cancel()) if(tasks.worker_cancel())
break; break;
@ -226,8 +226,8 @@ public:
else else
#endif #endif
{ {
for(int x = task.displace_x; x < task.displace_x + task.displace_w; x++) { for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) {
kernel_cpu_displace(kg, (uint4*)task.displace_input, (float3*)task.displace_offset, x); kernel_cpu_shader(kg, (uint4*)task.shader_input, (float3*)task.shader_output, task.shader_eval_type, x);
if(tasks.worker_cancel()) if(tasks.worker_cancel())
break; break;

@ -615,16 +615,16 @@ public:
cuda_pop_context(); cuda_pop_context();
} }
void displace(DeviceTask& task) void shader(DeviceTask& task)
{ {
cuda_push_context(); cuda_push_context();
CUfunction cuDisplace; CUfunction cuDisplace;
CUdeviceptr d_input = cuda_device_ptr(task.displace_input); CUdeviceptr d_input = cuda_device_ptr(task.shader_input);
CUdeviceptr d_offset = cuda_device_ptr(task.displace_offset); CUdeviceptr d_offset = cuda_device_ptr(task.shader_output);
/* get kernel function */ /* get kernel function */
cuda_assert(cuModuleGetFunction(&cuDisplace, cuModule, "kernel_cuda_displace")) cuda_assert(cuModuleGetFunction(&cuDisplace, cuModule, "kernel_cuda_shader"))
/* pass in parameters */ /* pass in parameters */
int offset = 0; int offset = 0;
@ -635,11 +635,14 @@ public:
cuda_assert(cuParamSetv(cuDisplace, offset, &d_offset, sizeof(d_offset))) cuda_assert(cuParamSetv(cuDisplace, offset, &d_offset, sizeof(d_offset)))
offset += sizeof(d_offset); offset += sizeof(d_offset);
int displace_x = task.displace_x; int shader_eval_type = task.shader_eval_type;
offset = cuda_align_up(offset, __alignof(displace_x)); offset = cuda_align_up(offset, __alignof(shader_eval_type));
cuda_assert(cuParamSeti(cuDisplace, offset, task.displace_x)) cuda_assert(cuParamSeti(cuDisplace, offset, task.shader_eval_type))
offset += sizeof(task.displace_x); offset += sizeof(task.shader_eval_type);
cuda_assert(cuParamSeti(cuDisplace, offset, task.shader_x))
offset += sizeof(task.shader_x);
cuda_assert(cuParamSetSize(cuDisplace, offset)) cuda_assert(cuParamSetSize(cuDisplace, offset))
@ -649,7 +652,7 @@ public:
#else #else
int xthreads = 8; int xthreads = 8;
#endif #endif
int xblocks = (task.displace_w + xthreads - 1)/xthreads; int xblocks = (task.shader_w + xthreads - 1)/xthreads;
cuda_assert(cuFuncSetCacheConfig(cuDisplace, CU_FUNC_CACHE_PREFER_L1)) cuda_assert(cuFuncSetCacheConfig(cuDisplace, CU_FUNC_CACHE_PREFER_L1))
cuda_assert(cuFuncSetBlockShape(cuDisplace, xthreads, 1, 1)) cuda_assert(cuFuncSetBlockShape(cuDisplace, xthreads, 1, 1))
@ -828,8 +831,8 @@ public:
tonemap(task); tonemap(task);
else if(task.type == DeviceTask::PATH_TRACE) else if(task.type == DeviceTask::PATH_TRACE)
path_trace(task); path_trace(task);
else if(task.type == DeviceTask::DISPLACE) else if(task.type == DeviceTask::SHADER)
displace(task); shader(task);
} }
void task_wait() void task_wait()

@ -306,8 +306,8 @@ public:
if(task.buffer) subtask.buffer = sub.ptr_map[task.buffer]; if(task.buffer) subtask.buffer = sub.ptr_map[task.buffer];
if(task.rng_state) subtask.rng_state = sub.ptr_map[task.rng_state]; if(task.rng_state) subtask.rng_state = sub.ptr_map[task.rng_state];
if(task.rgba) subtask.rgba = sub.ptr_map[task.rgba]; if(task.rgba) subtask.rgba = sub.ptr_map[task.rgba];
if(task.displace_input) subtask.displace_input = sub.ptr_map[task.displace_input]; if(task.shader_input) subtask.shader_input = sub.ptr_map[task.shader_input];
if(task.displace_offset) subtask.displace_offset = sub.ptr_map[task.displace_offset]; if(task.shader_output) subtask.shader_output = sub.ptr_map[task.shader_output];
sub.device->task_add(subtask); sub.device->task_add(subtask);
} }

@ -80,10 +80,10 @@ __kernel void kernel_ocl_tonemap(
kernel_film_tonemap(kg, rgba, buffer, sample, resolution, x, y, offset, stride); kernel_film_tonemap(kg, rgba, buffer, sample, resolution, x, y, offset, stride);
} }
/*__kernel void kernel_ocl_displace(__global uint4 *input, __global float3 *offset, int sx) /*__kernel void kernel_ocl_shader(__global uint4 *input, __global float3 *output, int type, int sx)
{ {
int x = sx + get_global_id(0); int x = sx + get_global_id(0);
kernel_displace(input, offset, x); kernel_shader_evaluate(input, output, (ShaderEvalType)type, x);
}*/ }*/

@ -216,11 +216,11 @@ void kernel_cpu_tonemap(KernelGlobals *kg, uchar4 *rgba, float4 *buffer, int sam
kernel_film_tonemap(kg, rgba, buffer, sample, resolution, x, y, offset, stride); kernel_film_tonemap(kg, rgba, buffer, sample, resolution, x, y, offset, stride);
} }
/* Displacement */ /* Shader Evaluation */
void kernel_cpu_displace(KernelGlobals *kg, uint4 *input, float3 *offset, int i) void kernel_cpu_shader(KernelGlobals *kg, uint4 *input, float3 *output, int type, int i)
{ {
kernel_displace(kg, input, offset, i); kernel_shader_evaluate(kg, input, output, (ShaderEvalType)type, i);
} }
CCL_NAMESPACE_END CCL_NAMESPACE_END

@ -44,10 +44,10 @@ extern "C" __global__ void kernel_cuda_tonemap(uchar4 *rgba, float4 *buffer, int
kernel_film_tonemap(NULL, rgba, buffer, sample, resolution, x, y, offset, stride); kernel_film_tonemap(NULL, rgba, buffer, sample, resolution, x, y, offset, stride);
} }
extern "C" __global__ void kernel_cuda_displace(uint4 *input, float3 *offset, int sx) extern "C" __global__ void kernel_cuda_shader(uint4 *input, float3 *output, int type, int sx)
{ {
int x = sx + blockDim.x*blockIdx.x + threadIdx.x; int x = sx + blockDim.x*blockIdx.x + threadIdx.x;
kernel_displace(NULL, input, offset, x); kernel_shader_evaluate(NULL, input, output, (ShaderEvalType)type, x);
} }

@ -40,14 +40,16 @@ void kernel_cpu_path_trace(KernelGlobals *kg, float4 *buffer, unsigned int *rng_
int sample, int x, int y, int offset, int stride); int sample, int x, int y, int offset, int stride);
void kernel_cpu_tonemap(KernelGlobals *kg, uchar4 *rgba, float4 *buffer, void kernel_cpu_tonemap(KernelGlobals *kg, uchar4 *rgba, float4 *buffer,
int sample, int resolution, int x, int y, int offset, int stride); int sample, int resolution, int x, int y, int offset, int stride);
void kernel_cpu_displace(KernelGlobals *kg, uint4 *input, float3 *offset, int i); void kernel_cpu_shader(KernelGlobals *kg, uint4 *input, float3 *output,
int type, int i);
#ifdef WITH_OPTIMIZED_KERNEL #ifdef WITH_OPTIMIZED_KERNEL
void kernel_cpu_optimized_path_trace(KernelGlobals *kg, float4 *buffer, unsigned int *rng_state, void kernel_cpu_optimized_path_trace(KernelGlobals *kg, float4 *buffer, unsigned int *rng_state,
int sample, int x, int y, int offset, int stride); int sample, int x, int y, int offset, int stride);
void kernel_cpu_optimized_tonemap(KernelGlobals *kg, uchar4 *rgba, float4 *buffer, void kernel_cpu_optimized_tonemap(KernelGlobals *kg, uchar4 *rgba, float4 *buffer,
int sample, int resolution, int x, int y, int offset, int stride); int sample, int resolution, int x, int y, int offset, int stride);
void kernel_cpu_optimized_displace(KernelGlobals *kg, uint4 *input, float3 *offset, int i); void kernel_cpu_optimized_shader(KernelGlobals *kg, uint4 *input, float3 *output,
int type, int i);
#endif #endif
CCL_NAMESPACE_END CCL_NAMESPACE_END

@ -18,17 +18,51 @@
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
__device void kernel_displace(KernelGlobals *kg, uint4 *input, float3 *offset, int i) __device void kernel_shader_evaluate(KernelGlobals *kg, uint4 *input, float3 *output, ShaderEvalType type, int i)
{ {
/* setup shader data */
ShaderData sd; ShaderData sd;
uint4 in = input[i]; uint4 in = input[i];
shader_setup_from_displace(kg, &sd, in.x, in.y, __int_as_float(in.z), __int_as_float(in.w)); float3 out;
/* evaluate */ if(type == SHADER_EVAL_DISPLACE) {
float3 P = sd.P; /* setup shader data */
shader_eval_displacement(kg, &sd); int object = in.x;
offset[i] = sd.P - P; int prim = in.y;
float u = __int_as_float(in.z);
float v = __int_as_float(in.w);
shader_setup_from_displace(kg, &sd, object, prim, u, v);
/* evaluate */
float3 P = sd.P;
shader_eval_displacement(kg, &sd);
out = sd.P - P;
}
else { // SHADER_EVAL_BACKGROUND
/* setup ray */
Ray ray;
ray.P = make_float3(0.0f, 0.0f, 0.0f);
ray.D = make_float3(__int_as_float(in.x), __int_as_float(in.y), __int_as_float(in.z));
ray.t = 0.0f;
#ifdef __RAY_DIFFERENTIALS__
ray.dD.dx = make_float3(0.0f, 0.0f, 0.0f);
ray.dD.dy = make_float3(0.0f, 0.0f, 0.0f);
ray.dP.dx = make_float3(0.0f, 0.0f, 0.0f);
ray.dP.dy = make_float3(0.0f, 0.0f, 0.0f);
#endif
/* setup shader data */
shader_setup_from_background(kg, &sd, &ray);
/* evaluate */
int flag = 0; /* we can't know which type of BSDF this is for */
out = shader_eval_background(kg, &sd, flag);
}
/* write output */
output[i] = out;
} }
CCL_NAMESPACE_END CCL_NAMESPACE_END

@ -47,11 +47,11 @@ void kernel_cpu_optimized_tonemap(KernelGlobals *kg, uchar4 *rgba, float4 *buffe
kernel_film_tonemap(kg, rgba, buffer, sample, resolution, x, y, offset, stride); kernel_film_tonemap(kg, rgba, buffer, sample, resolution, x, y, offset, stride);
} }
/* Displacement */ /* Shader Evaluate */
void kernel_cpu_optimized_displace(KernelGlobals *kg, uint4 *input, float3 *offset, int i) void kernel_cpu_optimized_shader(KernelGlobals *kg, uint4 *input, float3 *output, int type, int i)
{ {
kernel_displace(kg, input, offset, i); kernel_shader_evaluate(kg, input, output, (ShaderEvalType)type, i);
} }
CCL_NAMESPACE_END CCL_NAMESPACE_END

@ -78,6 +78,13 @@ CCL_NAMESPACE_BEGIN
//#define __MODIFY_TP__ //#define __MODIFY_TP__
//#define __QBVH__ //#define __QBVH__
/* Shader Evaluation */
enum ShaderEvalType {
SHADER_EVAL_DISPLACE,
SHADER_EVAL_BACKGROUND
};
/* Path Tracing */ /* Path Tracing */
enum PathTraceDimension { enum PathTraceDimension {

@ -30,7 +30,8 @@ shader node_hsv(
float t = clamp(Fac, 0.0, 1.0); float t = clamp(Fac, 0.0, 1.0);
color Color = rgb_to_hsv(ColorIn); color Color = rgb_to_hsv(ColorIn);
Color[0] += Hue - 0.5; // remember: fmod doesn't work for negative numbers
Color[0] += Hue + 0.5;
Color[0] = fmod(Color[0], 1.0); Color[0] = fmod(Color[0], 1.0);
Color[1] *= Saturation; Color[1] *= Saturation;
Color[2] *= Value; Color[2] *= Value;

@ -110,7 +110,8 @@ __device void svm_node_hsv(KernelGlobals *kg, ShaderData *sd, float *stack, uint
color = rgb_to_hsv(color); color = rgb_to_hsv(color);
color.x += hue - 0.5f; // remember: fmod doesn't work for negative numbers
color.x += hue + 0.5f;
color.x = fmod(color.x, 1.0f); color.x = fmod(color.x, 1.0f);
color.y *= sat; color.y *= sat;
color.z *= val; color.z *= val;

@ -25,9 +25,9 @@ __device void svm_node_normal(KernelGlobals *kg, ShaderData *sd, float *stack, u
float3 normal = stack_load_float3(stack, in_normal_offset); float3 normal = stack_load_float3(stack, in_normal_offset);
float3 direction; float3 direction;
direction.x = node1.x; direction.x = __int_as_float(node1.x);
direction.y = node1.y; direction.y = __int_as_float(node1.y);
direction.z = node1.z; direction.z = __int_as_float(node1.z);
direction = normalize(direction); direction = normalize(direction);
if (stack_valid(out_normal_offset)) if (stack_valid(out_normal_offset))

@ -89,25 +89,26 @@ bool MeshManager::displace(Device *device, Scene *scene, Mesh *mesh, Progress& p
return false; return false;
/* run device task */ /* run device task */
device_vector<float3> d_offset; device_vector<float3> d_output;
d_offset.resize(d_input.size()); d_output.resize(d_input.size());
device->mem_alloc(d_input, MEM_READ_ONLY); device->mem_alloc(d_input, MEM_READ_ONLY);
device->mem_copy_to(d_input); device->mem_copy_to(d_input);
device->mem_alloc(d_offset, MEM_WRITE_ONLY); device->mem_alloc(d_output, MEM_WRITE_ONLY);
DeviceTask task(DeviceTask::DISPLACE); DeviceTask task(DeviceTask::SHADER);
task.displace_input = d_input.device_pointer; task.shader_input = d_input.device_pointer;
task.displace_offset = d_offset.device_pointer; task.shader_output = d_output.device_pointer;
task.displace_x = 0; task.shader_eval_type = SHADER_EVAL_DISPLACE;
task.displace_w = d_input.size(); task.shader_x = 0;
task.shader_w = d_input.size();
device->task_add(task); device->task_add(task);
device->task_wait(); device->task_wait();
device->mem_copy_from(d_offset, 0, sizeof(float3)*d_offset.size()); device->mem_copy_from(d_output, 0, sizeof(float3)*d_output.size());
device->mem_free(d_input); device->mem_free(d_input);
device->mem_free(d_offset); device->mem_free(d_output);
if(progress.get_cancel()) if(progress.get_cancel())
return false; return false;
@ -117,7 +118,7 @@ bool MeshManager::displace(Device *device, Scene *scene, Mesh *mesh, Progress& p
done.resize(mesh->verts.size(), false); done.resize(mesh->verts.size(), false);
int k = 0; int k = 0;
float3 *offset = (float3*)d_offset.data_pointer; float3 *offset = (float3*)d_output.data_pointer;
for(size_t i = 0; i < mesh->triangles.size(); i++) { for(size_t i = 0; i < mesh->triangles.size(); i++) {
Mesh::Triangle t = mesh->triangles[i]; Mesh::Triangle t = mesh->triangles[i];

@ -0,0 +1,46 @@
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ***** END GPL LICENSE BLOCK *****
set(INC
.
intern
../../extern/Eigen3
)
set(SRC
intern/manifold_table.cpp
intern/marching_cubes_table.cpp
intern/octree.cpp
intern/Projections.cpp
intern/cubes.h
intern/GeoCommon.h
intern/manifold_table.h
intern/marching_cubes_table.h
intern/MemoryAllocator.h
intern/ModelReader.h
intern/octree.h
intern/Projections.h
intern/Queue.h
intern/dualcon_c_api.cpp
dualcon.h
)
blender_add_lib(bf_intern_dualcon "${SRC}" "${INC}" "")

@ -0,0 +1,9 @@
#!/usr/bin/python
Import ('env')
sources = env.Glob('intern/*.cpp')
incs = '. ../../extern/Eigen3'
defs = ''
env.BlenderLib ('bf_intern_dualcon', sources, Split(incs), Split(defs), libtype=['intern'], priority=[100] )

95
intern/dualcon/dualcon.h Normal file

@ -0,0 +1,95 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Nicholas Bishop
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef DUALCON_H
#define DUALCON_H
#ifdef __cplusplus
extern "C" {
#endif
typedef float (*DualConCo)[3];
typedef unsigned int (*DualConFaces)[4];
struct DerivedMesh;
typedef struct DualConInput {
DualConCo co;
int co_stride;
int totco;
DualConFaces faces;
int face_stride;
int totface;
float min[3], max[3];
} DualConInput;
/* callback for allocating memory for output */
typedef void *(*DualConAllocOutput)(int totvert, int totquad);
/* callback for adding a new vertex to the output */
typedef void (*DualConAddVert)(void *output, const float co[3]);
/* callback for adding a new quad to the output */
typedef void (*DualConAddQuad)(void *output, const int vert_indices[4]);
typedef enum {
DUALCON_FLOOD_FILL = 1,
} DualConFlags;
typedef enum {
/* blocky */
DUALCON_CENTROID,
/* smooth */
DUALCON_MASS_POINT,
/* keeps sharp edges */
DUALCON_SHARP_FEATURES,
} DualConMode;
/* Usage:
The three callback arguments are used for creating the output
mesh. The alloc_output callback takes the total number of vertices
and faces (quads) that will be in the output. It should allocate
and return a structure to hold the output mesh. The add_vert and
add_quad callbacks will then be called for each new vertex and
quad, and the callback should add the new mesh elements to the
structure.
*/
void *dualcon(const DualConInput *input_mesh,
/* callbacks for output */
DualConAllocOutput alloc_output,
DualConAddVert add_vert,
DualConAddQuad add_quad,
/* flags and settings to control the remeshing
algorithm */
DualConFlags flags,
DualConMode mode,
float threshold,
float hermite_num,
float scale,
int depth);
#ifdef __cplusplus
}
#endif
#endif

@ -0,0 +1,69 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Tao Ju
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef GEOCOMMON_H
#define GEOCOMMON_H
#define UCHAR unsigned char
#define USHORT unsigned short
#define USE_MINIMIZER
/**
* Structure definitions for points and triangles.
*
* @author Tao Ju
*/
// 3d point with integer coordinates
typedef struct
{
int x, y, z;
} Point3i;
typedef struct
{
Point3i begin;
Point3i end;
} BoundingBox;
// triangle that points to three vertices
typedef struct
{
float vt[3][3] ;
} Triangle;
// 3d point with float coordinates
typedef struct
{
float x, y, z;
} Point3f;
typedef struct
{
Point3f begin;
Point3f end;
} BoundingBoxf;
#endif

@ -0,0 +1,219 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Tao Ju
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef MEMORYALLOCATOR_H
#define MEMORYALLOCATOR_H
#include <stdio.h>
#include <stdlib.h>
#define HEAP_BASE 16
#define UCHAR unsigned char
/**
* Customized memory allocators that allocates/deallocates memory in chunks
*
* @author Tao Ju
*/
/**
* Base class of memory allocators
*/
class VirtualMemoryAllocator
{
public:
virtual UCHAR * allocate( ) = 0 ;
virtual void deallocate( UCHAR * obj ) = 0 ;
virtual void destroy( ) = 0 ;
virtual void printInfo( ) = 0 ;
virtual int getAllocated( ) = 0 ;
virtual int getAll( ) = 0 ;
virtual int getBytes( ) = 0 ;
};
/**
* Dynamic memory allocator - allows allocation/deallocation
*
* Note: there are 4 bytes overhead for each allocated yet unused object.
*/
template < int N >
class MemoryAllocator : public VirtualMemoryAllocator
{
private:
/// Constants
int HEAP_UNIT, HEAP_MASK ;
/// Data array
UCHAR ** data ;
/// Allocation stack
UCHAR *** stack ;
/// Number of data blocks
int datablocknum ;
/// Number of stack blocks
int stackblocknum ;
/// Size of stack
int stacksize ;
/// Number of available objects on stack
int available ;
/**
* Allocate a memory block
*/
void allocateDataBlock ( )
{
// Allocate a data block
datablocknum += 1 ;
data = ( UCHAR ** )realloc( data, sizeof ( UCHAR * ) * datablocknum ) ;
data[ datablocknum - 1 ] = ( UCHAR * )malloc( HEAP_UNIT * N ) ;
// Update allocation stack
for ( int i = 0 ; i < HEAP_UNIT ; i ++ )
{
stack[ 0 ][ i ] = ( data[ datablocknum - 1 ] + i * N ) ;
}
available = HEAP_UNIT ;
}
/**
* Allocate a stack block, to store more deallocated objects
*/
void allocateStackBlock( )
{
// Allocate a stack block
stackblocknum += 1 ;
stacksize += HEAP_UNIT ;
stack = ( UCHAR *** )realloc( stack, sizeof ( UCHAR ** ) * stackblocknum ) ;
stack[ stackblocknum - 1 ] = ( UCHAR ** )malloc( HEAP_UNIT * sizeof ( UCHAR * ) ) ;
}
public:
/**
* Constructor
*/
MemoryAllocator( )
{
HEAP_UNIT = 1 << HEAP_BASE ;
HEAP_MASK = ( 1 << HEAP_BASE ) - 1 ;
data = ( UCHAR ** )malloc( sizeof( UCHAR * ) ) ;
data[ 0 ] = ( UCHAR * )malloc( HEAP_UNIT * N ) ;
datablocknum = 1 ;
stack = ( UCHAR *** )malloc( sizeof ( UCHAR ** ) ) ;
stack[ 0 ] = ( UCHAR ** )malloc( HEAP_UNIT * sizeof ( UCHAR * ) ) ;
stackblocknum = 1 ;
stacksize = HEAP_UNIT ;
available = HEAP_UNIT ;
for ( int i = 0 ; i < HEAP_UNIT ; i ++ )
{
stack[ 0 ][ i ] = ( data[ 0 ] + i * N ) ;
}
}
/**
* Destructor
*/
void destroy( )
{
int i ;
for ( i = 0 ; i < datablocknum ; i ++ )
{
free( data[ i ] ) ;
}
for ( i = 0 ; i < stackblocknum ; i ++ )
{
free( stack[ i ] ) ;
}
free( data ) ;
free( stack ) ;
}
/**
* Allocation method
*/
UCHAR * allocate ( )
{
if ( available == 0 )
{
allocateDataBlock ( ) ;
}
// printf("Allocating %d\n", header[ allocated ]) ;
available -- ;
return stack[ available >> HEAP_BASE ][ available & HEAP_MASK ] ;
}
/**
* De-allocation method
*/
void deallocate ( UCHAR * obj )
{
if ( available == stacksize )
{
allocateStackBlock ( ) ;
}
// printf("De-allocating %d\n", ( obj - data ) / N ) ;
stack[ available >> HEAP_BASE ][ available & HEAP_MASK ] = obj ;
available ++ ;
// printf("%d %d\n", allocated, header[ allocated ]) ;
}
/**
* Print information
*/
void printInfo ( )
{
printf("Bytes: %d Used: %d Allocated: %d Maxfree: %d\n", getBytes(), getAllocated(), getAll(), stacksize ) ;
}
/**
* Query methods
*/
int getAllocated( )
{
return HEAP_UNIT * datablocknum - available ;
};
int getAll( )
{
return HEAP_UNIT * datablocknum ;
};
int getBytes( )
{
return N ;
};
};
#endif

@ -0,0 +1,64 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Tao Ju
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef MODELREADER_H
#define MODELREADER_H
#include "GeoCommon.h"
/*
* Virtual class for input file readers
*
* @author Tao Ju
*/
class ModelReader
{
public:
/// Constructor
ModelReader(){} ;
/// Get next triangle
virtual Triangle* getNextTriangle( ) = 0 ;
virtual int getNextTriangle( int t[3] ) = 0 ;
/// Get bounding box
virtual float getBoundingBox ( float origin[3] ) = 0 ;
/// Get number of triangles
virtual int getNumTriangles ( ) = 0 ;
/// Get storage size
virtual int getMemory ( ) = 0 ;
/// Reset file reading location
virtual void reset( ) = 0 ;
/// For explicit vertex models
virtual int getNumVertices( ) = 0 ;
virtual void getNextVertex( float v[3] ) = 0 ;
virtual void printInfo ( ) = 0 ;
};
#endif

@ -0,0 +1,76 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Tao Ju
*
* ***** END GPL LICENSE BLOCK *****
*/
#include <math.h>
#include "Projections.h"
const int vertmap[8][3] = {
{0, 0, 0},
{0, 0, 1},
{0, 1, 0},
{0, 1, 1},
{1, 0, 0},
{1, 0, 1},
{1, 1, 0},
{1, 1, 1}
};
const int centmap[3][3][3][2] = {
{{{0, 0}, {0, 1}, {1, 1}},
{{0, 2}, {0, 3}, {1, 3}},
{{2, 2}, {2, 3}, {3, 3}}
},
{{{0, 4}, {0, 5}, {1, 5}},
{{0, 6}, {0, 7}, {1, 7}},
{{2, 6}, {2, 7}, {3, 7}}
},
{{{4, 4}, {4, 5}, {5, 5}},
{{4, 6}, {4, 7}, {5, 7}},
{{6, 6}, {6, 7}, {7, 7}}
}
};
const int edgemap[12][2] = {
{0, 4},
{1, 5},
{2, 6},
{3, 7},
{0, 2},
{1, 3},
{4, 6},
{5, 7},
{0, 1},
{2, 3},
{4, 5},
{6, 7}
};
const int facemap[6][4] = {
{0, 1, 2, 3},
{4, 5, 6, 7},
{0, 1, 4, 5},
{2, 3, 6, 7},
{0, 2, 4, 6},
{1, 3, 5, 7}
};

@ -0,0 +1,845 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Tao Ju
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef PROJECTIONS_H
#define PROJECTIONS_H
#include <stdio.h>
#include <stdlib.h>
#define CONTAINS_INDEX
#define GRID_DIMENSION 20
#if defined(_WIN32) && !defined(__MINGW32__)
#define LONG __int64
#else
#include <stdint.h>
#define LONG int64_t
#endif
#define UCHAR unsigned char
/**
* Structures and classes for computing projections of triangles
* onto separating axes during scan conversion
*
* @author Tao Ju
*/
extern const int vertmap[8][3];
extern const int centmap[3][3][3][2];
extern const int edgemap[12][2];
extern const int facemap[6][4];
/**
* Structure for the projections inheritable from parent
*/
struct InheritableProjections
{
/// Projections of triangle
LONG trigProj[13][2] ;
/// Projections of triangle vertices on primary axes
LONG trigVertProj[13][3] ;
/// Projections of triangle edges
LONG trigEdgeProj[13][3][2] ;
/// Normal of the triangle
double norm[3] ;
double normA, normB ;
/// End points along each axis
//int cubeEnds[13][2] ;
/// Error range on each axis
/// LONG errorProj[13];
#ifdef CONTAINS_INDEX
/// Index of polygon
int index ;
#endif
};
/**
* Class for projections of cube / triangle vertices on the separating axes
*/
class Projections
{
public:
/// Inheritable portion
InheritableProjections* inherit ;
/// Projections of the cube vertices
LONG cubeProj[13][6] ;
public:
Projections( )
{
}
/**
* Construction
* from a cube (axes aligned) and triangle
*/
Projections( LONG cube[2][3], LONG trig[3][3], LONG error, int triind )
{
int i, j ;
inherit = new InheritableProjections ;
#ifdef CONTAINS_INDEX
inherit->index = triind ;
#endif
/// Create axes
LONG axes[13][3] ;
// Cube faces
axes[0][0] = 1 ;
axes[0][1] = 0 ;
axes[0][2] = 0 ;
axes[1][0] = 0 ;
axes[1][1] = 1 ;
axes[1][2] = 0 ;
axes[2][0] = 0 ;
axes[2][1] = 0 ;
axes[2][2] = 1 ;
// Triangle face
LONG trigedge[3][3] ;
for ( i = 0 ; i < 3 ; i ++ )
{
for ( j = 0 ; j < 3 ; j ++ )
{
trigedge[i][j] = trig[(i+1)%3][j] - trig[i][j] ;
}
}
crossProduct( trigedge[0], trigedge[1], axes[3] ) ;
/// Normalize face normal and store
double dedge1[] = { (double) trig[1][0] - (double) trig[0][0],
(double) trig[1][1] - (double) trig[0][1],
(double) trig[1][2] - (double) trig[0][2] } ;
double dedge2[] = { (double) trig[2][0] - (double) trig[1][0],
(double) trig[2][1] - (double) trig[1][1],
(double) trig[2][2] - (double) trig[1][2] } ;
crossProduct( dedge1, dedge2, inherit->norm ) ;
normalize( inherit->norm ) ;
// inherit->normA = norm[ 0 ] ;
// inherit->normB = norm[ 2 ] > 0 ? norm[ 1 ] : 2 + norm[ 1 ] ;
// Face edges and triangle edges
int ct = 4 ;
for ( i = 0 ; i < 3 ; i ++ )
for ( j = 0 ; j < 3 ; j ++ )
{
crossProduct( axes[j], trigedge[i], axes[ct] ) ;
ct ++ ;
}
/// Generate projections
LONG cubeedge[3][3] ;
for ( i = 0 ; i < 3 ; i ++ )
{
for ( j = 0 ; j < 3 ; j ++ )
{
cubeedge[i][j] = 0 ;
}
cubeedge[i][i] = cube[1][i] - cube[0][i] ;
}
for ( j = 0 ; j < 13 ; j ++ )
{
// Origin
cubeProj[j][0] = dotProduct( axes[j], cube[0] ) ;
// 3 direction vectors
for ( i = 1 ; i < 4 ; i ++ )
{
cubeProj[j][i] = dotProduct( axes[j], cubeedge[i-1] ) ;
}
// Offsets of 2 ends of cube projection
LONG max = 0 ;
LONG min = 0 ;
for ( i = 1 ; i < 8 ; i ++ )
{
LONG proj = vertmap[i][0] * cubeProj[j][1] + vertmap[i][1] * cubeProj[j][2] + vertmap[i][2] * cubeProj[j][3] ;
if ( proj > max )
{
max = proj ;
}
if ( proj < min )
{
min = proj ;
}
}
cubeProj[j][4] = min ;
cubeProj[j][5] = max ;
}
for ( j = 0 ; j < 13 ; j ++ )
{
LONG vts[3] = { dotProduct( axes[j], trig[0] ),
dotProduct( axes[j], trig[1] ),
dotProduct( axes[j], trig[2] ) } ;
// Vertex
inherit->trigVertProj[j][0] = vts[0] ;
inherit->trigVertProj[j][1] = vts[1] ;
inherit->trigVertProj[j][2] = vts[2] ;
// Edge
for ( i = 0 ; i < 3 ; i ++ )
{
if ( vts[i] < vts[(i+1) % 3] )
{
inherit->trigEdgeProj[j][i][0] = vts[i] ;
inherit->trigEdgeProj[j][i][1] = vts[(i+1) % 3] ;
}
else
{
inherit->trigEdgeProj[j][i][1] = vts[i] ;
inherit->trigEdgeProj[j][i][0] = vts[(i+1) % 3] ;
}
}
// Triangle
inherit->trigProj[j][0] = vts[0] ;
inherit->trigProj[j][1] = vts[0] ;
for ( i = 1 ; i < 3 ; i ++ )
{
if ( vts[i] < inherit->trigProj[j][0] )
{
inherit->trigProj[j][0] = vts[i] ;
}
if ( vts[i] > inherit->trigProj[j][1] )
{
inherit->trigProj[j][1] = vts[i] ;
}
}
}
}
/**
* Construction
* from a parent Projections object and the index of the children
*/
Projections ( Projections* parent )
{
// Copy inheritable projections
this->inherit = parent->inherit ;
// Shrink cube projections
for ( int i = 0 ; i < 13 ; i ++ )
{
cubeProj[i][0] = parent->cubeProj[i][0] ;
for ( int j = 1 ; j < 6 ; j ++ )
{
cubeProj[i][j] = parent->cubeProj[i][j] >> 1 ;
}
}
};
Projections ( Projections* parent, int box[3], int depth )
{
int mask = ( 1 << depth ) - 1 ;
int nbox[3] = { box[0] & mask, box[1] & mask, box[2] & mask } ;
// Copy inheritable projections
this->inherit = parent->inherit ;
// Shrink cube projections
for ( int i = 0 ; i < 13 ; i ++ )
{
for ( int j = 1 ; j < 6 ; j ++ )
{
cubeProj[i][j] = parent->cubeProj[i][j] >> depth ;
}
cubeProj[i][0] = parent->cubeProj[i][0] + nbox[0] * cubeProj[i][1] + nbox[1] * cubeProj[i][2] + nbox[2] * cubeProj[i][3] ;
}
};
/**
* Testing intersection based on vertex/edge masks
*/
int getIntersectionMasks( UCHAR cedgemask, UCHAR& edgemask )
{
int i, j ;
edgemask = cedgemask ;
// Pre-processing
/*
if ( cvertmask & 1 )
{
edgemask |= 5 ;
}
if ( cvertmask & 2 )
{
edgemask |= 3 ;
}
if ( cvertmask & 4 )
{
edgemask |= 6 ;
}
*/
// Test axes for edge intersection
UCHAR bit = 1 ;
for ( j = 0 ; j < 3 ; j ++ )
{
if ( edgemask & bit )
{
for ( i = 0 ; i < 13 ; i ++ )
{
LONG proj0 = cubeProj[i][0] + cubeProj[i][4] ;
LONG proj1 = cubeProj[i][0] + cubeProj[i][5] ;
if ( proj0 > inherit->trigEdgeProj[i][j][1] ||
proj1 < inherit->trigEdgeProj[i][j][0] )
{
edgemask &= ( ~ bit ) ;
break ;
}
}
}
bit <<= 1 ;
}
/*
if ( edgemask != 0 )
{
printf("%d %d\n", cedgemask, edgemask) ;
}
*/
// Test axes for triangle intersection
if ( edgemask )
{
return 1 ;
}
for ( i = 3 ; i < 13 ; i ++ )
{
LONG proj0 = cubeProj[i][0] + cubeProj[i][4] ;
LONG proj1 = cubeProj[i][0] + cubeProj[i][5] ;
if ( proj0 > inherit->trigProj[i][1] ||
proj1 < inherit->trigProj[i][0] )
{
return 0 ;
}
}
return 1 ;
}
/**
* Retrieving children masks using PRIMARY AXES
*/
UCHAR getChildrenMasks( UCHAR cvertmask, UCHAR vertmask[8] )
{
int i, j, k ;
int bmask[3][2] = {{0,0},{0,0},{0,0}} ;
int vmask[3][3][2] = {{{0,0},{0,0},{0,0}},{{0,0},{0,0},{0,0}},{{0,0},{0,0},{0,0}}} ;
UCHAR boxmask = 0 ;
LONG len = cubeProj[0][1] >> 1 ;
for ( i = 0 ; i < 3 ; i ++ )
{
LONG mid = cubeProj[i][0] + len ;
// Check bounding box
if ( mid >= inherit->trigProj[i][0] )
{
bmask[i][0] = 1 ;
}
if ( mid <= inherit->trigProj[i][1] )
{
bmask[i][1] = 1 ;
}
// Check vertex mask
if ( cvertmask )
{
for ( j = 0 ; j < 3 ; j ++ )
{
if ( cvertmask & ( 1 << j ) )
{
// Only check if it's contained this node
if ( mid >= inherit->trigVertProj[i][j] )
{
vmask[i][j][0] = 1 ;
}
if ( mid <= inherit->trigVertProj[i][j] )
{
vmask[i][j][1] = 1 ;
}
}
}
}
/*
// Check edge mask
if ( cedgemask )
{
for ( j = 0 ; j < 3 ; j ++ )
{
if ( cedgemask & ( 1 << j ) )
{
// Only check if it's contained this node
if ( mid >= inherit->trigEdgeProj[i][j][0] )
{
emask[i][j][0] = 1 ;
}
if ( mid <= inherit->trigEdgeProj[i][j][1] )
{
emask[i][j][1] = 1 ;
}
}
}
}
*/
}
// Fill in masks
int ct = 0 ;
for ( i = 0 ; i < 2 ; i ++ )
for ( j = 0 ; j < 2 ; j ++ )
for ( k = 0 ; k < 2 ; k ++ )
{
boxmask |= ( ( bmask[0][i] & bmask[1][j] & bmask[2][k] ) << ct ) ;
vertmask[ct] = (( vmask[0][0][i] & vmask[1][0][j] & vmask[2][0][k] ) |
(( vmask[0][1][i] & vmask[1][1][j] & vmask[2][1][k] ) << 1 ) |
(( vmask[0][2][i] & vmask[1][2][j] & vmask[2][2][k] ) << 2 ) ) ;
/*
edgemask[ct] = (( emask[0][0][i] & emask[1][0][j] & emask[2][0][k] ) |
(( emask[0][1][i] & emask[1][1][j] & emask[2][1][k] ) << 1 ) |
(( emask[0][2][i] & emask[1][2][j] & emask[2][2][k] ) << 2 ) ) ;
edgemask[ct] = cedgemask ;
*/
ct ++ ;
}
// Return bounding box masks
return boxmask ;
}
UCHAR getBoxMask( )
{
int i, j, k ;
int bmask[3][2] = {{0,0},{0,0},{0,0}} ;
UCHAR boxmask = 0 ;
LONG len = cubeProj[0][1] >> 1 ;
for ( i = 0 ; i < 3 ; i ++ )
{
LONG mid = cubeProj[i][0] + len ;
// Check bounding box
if ( mid >= inherit->trigProj[i][0] )
{
bmask[i][0] = 1 ;
}
if ( mid <= inherit->trigProj[i][1] )
{
bmask[i][1] = 1 ;
}
}
// Fill in masks
int ct = 0 ;
for ( i = 0 ; i < 2 ; i ++ )
for ( j = 0 ; j < 2 ; j ++ )
for ( k = 0 ; k < 2 ; k ++ )
{
boxmask |= ( ( bmask[0][i] & bmask[1][j] & bmask[2][k] ) << ct ) ;
ct ++ ;
}
// Return bounding box masks
return boxmask ;
}
/**
* Get projections for sub-cubes (simple axes)
*/
void getSubProjectionsSimple( Projections* p[8] )
{
// Process the axes cooresponding to the triangle's normal
int ind = 3 ;
LONG len = cubeProj[ 0 ][ 1 ] >> 1 ;
LONG trigproj[3] = { cubeProj[ ind ][ 1 ] >> 1, cubeProj[ ind ][ 2 ] >> 1, cubeProj[ ind ][ 3 ] >> 1 } ;
int ct = 0 ;
for ( int i = 0 ; i < 2 ; i ++ )
for ( int j = 0 ; j < 2 ; j ++ )
for ( int k = 0 ; k < 2 ; k ++ )
{
p[ct] = new Projections( ) ;
p[ct]->inherit = inherit ;
p[ct]->cubeProj[ 0 ][ 0 ] = cubeProj[ 0 ][ 0 ] + i * len ;
p[ct]->cubeProj[ 1 ][ 0 ] = cubeProj[ 1 ][ 0 ] + j * len ;
p[ct]->cubeProj[ 2 ][ 0 ] = cubeProj[ 2 ][ 0 ] + k * len ;
p[ct]->cubeProj[ 0 ][ 1 ] = len ;
for ( int m = 1 ; m < 4 ; m ++ )
{
p[ct]->cubeProj[ ind ][ m ] = trigproj[ m - 1 ] ;
}
p[ct]->cubeProj[ ind ][ 0 ] = cubeProj[ ind ][0] + i * trigproj[0] + j * trigproj[1] + k * trigproj[2] ;
ct ++ ;
}
}
/**
* Shifting a cube to a new origin
*/
void shift ( int off[3] )
{
for ( int i = 0 ; i < 13 ; i ++ )
{
cubeProj[i][0] += off[0] * cubeProj[i][1] + off[1] * cubeProj[i][2] + off[2] * cubeProj[i][3] ;
}
}
void shiftNoPrimary ( int off[3] )
{
for ( int i = 3 ; i < 13 ; i ++ )
{
cubeProj[i][0] += off[0] * cubeProj[i][1] + off[1] * cubeProj[i][2] + off[2] * cubeProj[i][3] ;
}
}
/**
* Method to test intersection of the triangle and the cube
*/
int isIntersecting ( )
{
for ( int i = 0 ; i < 13 ; i ++ )
{
/*
LONG proj0 = cubeProj[i][0] +
vertmap[inherit->cubeEnds[i][0]][0] * cubeProj[i][1] +
vertmap[inherit->cubeEnds[i][0]][1] * cubeProj[i][2] +
vertmap[inherit->cubeEnds[i][0]][2] * cubeProj[i][3] ;
LONG proj1 = cubeProj[i][0] +
vertmap[inherit->cubeEnds[i][1]][0] * cubeProj[i][1] +
vertmap[inherit->cubeEnds[i][1]][1] * cubeProj[i][2] +
vertmap[inherit->cubeEnds[i][1]][2] * cubeProj[i][3] ;
*/
LONG proj0 = cubeProj[i][0] + cubeProj[i][4] ;
LONG proj1 = cubeProj[i][0] + cubeProj[i][5] ;
if ( proj0 > inherit->trigProj[i][1] ||
proj1 < inherit->trigProj[i][0] )
{
return 0 ;
}
}
return 1 ;
};
int isIntersectingNoPrimary ( )
{
for ( int i = 3 ; i < 13 ; i ++ )
{
/*
LONG proj0 = cubeProj[i][0] +
vertmap[inherit->cubeEnds[i][0]][0] * cubeProj[i][1] +
vertmap[inherit->cubeEnds[i][0]][1] * cubeProj[i][2] +
vertmap[inherit->cubeEnds[i][0]][2] * cubeProj[i][3] ;
LONG proj1 = cubeProj[i][0] +
vertmap[inherit->cubeEnds[i][1]][0] * cubeProj[i][1] +
vertmap[inherit->cubeEnds[i][1]][1] * cubeProj[i][2] +
vertmap[inherit->cubeEnds[i][1]][2] * cubeProj[i][3] ;
*/
LONG proj0 = cubeProj[i][0] + cubeProj[i][4] ;
LONG proj1 = cubeProj[i][0] + cubeProj[i][5] ;
if ( proj0 > inherit->trigProj[i][1] ||
proj1 < inherit->trigProj[i][0] )
{
return 0 ;
}
}
return 1 ;
};
/**
* Method to test intersection of the triangle and one edge
*/
int isIntersecting ( int edgeInd )
{
for ( int i = 0 ; i < 13 ; i ++ )
{
LONG proj0 = cubeProj[i][0] +
vertmap[edgemap[edgeInd][0]][0] * cubeProj[i][1] +
vertmap[edgemap[edgeInd][0]][1] * cubeProj[i][2] +
vertmap[edgemap[edgeInd][0]][2] * cubeProj[i][3] ;
LONG proj1 = cubeProj[i][0] +
vertmap[edgemap[edgeInd][1]][0] * cubeProj[i][1] +
vertmap[edgemap[edgeInd][1]][1] * cubeProj[i][2] +
vertmap[edgemap[edgeInd][1]][2] * cubeProj[i][3] ;
if ( proj0 < proj1 )
{
if ( proj0 > inherit->trigProj[i][1] ||
proj1 < inherit->trigProj[i][0] )
{
return 0 ;
}
}
else
{
if ( proj1 > inherit->trigProj[i][1] ||
proj0 < inherit->trigProj[i][0] )
{
return 0 ;
}
}
}
// printf( "Intersecting: %d %d\n", edgemap[edgeInd][0], edgemap[edgeInd][1] ) ;
return 1 ;
};
/**
* Method to test intersection of one triangle edge and one cube face
*/
int isIntersecting ( int edgeInd, int faceInd )
{
for ( int i = 0 ; i < 13 ; i ++ )
{
LONG trigproj0 = inherit->trigVertProj[i][edgeInd] ;
LONG trigproj1 = inherit->trigVertProj[i][(edgeInd+1)%3] ;
if ( trigproj0 < trigproj1 )
{
int t1 = 1 , t2 = 1 ;
for ( int j = 0 ; j < 4 ; j ++ )
{
LONG proj = cubeProj[i][0] +
vertmap[facemap[faceInd][j]][0] * cubeProj[i][1] +
vertmap[facemap[faceInd][j]][1] * cubeProj[i][2] +
vertmap[facemap[faceInd][j]][2] * cubeProj[i][3] ;
if ( proj >= trigproj0 )
{
t1 = 0 ;
}
if ( proj <= trigproj1 )
{
t2 = 0 ;
}
}
if ( t1 || t2 )
{
return 0 ;
}
}
else
{
int t1 = 1 , t2 = 1 ;
for ( int j = 0 ; j < 4 ; j ++ )
{
LONG proj = cubeProj[i][0] +
vertmap[facemap[faceInd][j]][0] * cubeProj[i][1] +
vertmap[facemap[faceInd][j]][1] * cubeProj[i][2] +
vertmap[facemap[faceInd][j]][2] * cubeProj[i][3] ;
if ( proj >= trigproj1 )
{
t1 = 0 ;
}
if ( proj <= trigproj0 )
{
t2 = 0 ;
}
}
if ( t1 || t2 )
{
return 0 ;
}
}
}
return 1 ;
};
int isIntersectingPrimary ( int edgeInd )
{
for ( int i = 0 ; i < 13 ; i ++ )
{
LONG proj0 = cubeProj[i][0] ;
LONG proj1 = cubeProj[i][0] + cubeProj[i][edgeInd + 1] ;
if ( proj0 < proj1 )
{
if ( proj0 > inherit->trigProj[i][1] ||
proj1 < inherit->trigProj[i][0] )
{
return 0 ;
}
}
else
{
if ( proj1 > inherit->trigProj[i][1] ||
proj0 < inherit->trigProj[i][0] )
{
return 0 ;
}
}
}
// printf( "Intersecting: %d %d\n", edgemap[edgeInd][0], edgemap[edgeInd][1] ) ;
return 1 ;
};
double getIntersection ( int edgeInd )
{
int i = 3 ;
LONG proj0 = cubeProj[i][0] +
vertmap[edgemap[edgeInd][0]][0] * cubeProj[i][1] +
vertmap[edgemap[edgeInd][0]][1] * cubeProj[i][2] +
vertmap[edgemap[edgeInd][0]][2] * cubeProj[i][3] ;
LONG proj1 = cubeProj[i][0] +
vertmap[edgemap[edgeInd][1]][0] * cubeProj[i][1] +
vertmap[edgemap[edgeInd][1]][1] * cubeProj[i][2] +
vertmap[edgemap[edgeInd][1]][2] * cubeProj[i][3] ;
LONG proj2 = inherit->trigProj[i][1] ;
/*
if ( proj0 < proj1 )
{
if ( proj2 < proj0 || proj2 > proj1 )
{
return -1 ;
}
}
else
{
if ( proj2 < proj1 || proj2 > proj0 )
{
return -1 ;
}
}
*/
double alpha = (double)( proj2 - proj0 ) / (double)( proj1 - proj0 ) ;
/*
if ( alpha < 0 )
{
alpha = 0.5 ;
}
else if ( alpha > 1 )
{
alpha = 0.5 ;
}
*/
return alpha ;
};
float getIntersectionPrimary ( int edgeInd )
{
int i = 3 ;
LONG proj0 = cubeProj[i][0] ;
LONG proj1 = cubeProj[i][0] + cubeProj[i][edgeInd + 1] ;
LONG proj2 = inherit->trigProj[i][1] ;
// double alpha = (double)( ( proj2 - proj0 ) * cubeProj[edgeInd][edgeInd + 1] ) / (double)( proj1 - proj0 ) ;
double alpha = (double)( ( proj2 - proj0 ) ) / (double)( proj1 - proj0 ) ;
if ( alpha < 0 )
{
alpha = 0.5 ;
}
else if ( alpha > 1 )
{
alpha = 0.5 ;
}
return (float)alpha ;
};
/**
* Method to perform cross-product
*/
void crossProduct ( LONG a[3], LONG b[3], LONG res[3] )
{
res[0] = a[1] * b[2] - a[2] * b[1] ;
res[1] = a[2] * b[0] - a[0] * b[2] ;
res[2] = a[0] * b[1] - a[1] * b[0] ;
}
void crossProduct ( double a[3], double b[3], double res[3] )
{
res[0] = a[1] * b[2] - a[2] * b[1] ;
res[1] = a[2] * b[0] - a[0] * b[2] ;
res[2] = a[0] * b[1] - a[1] * b[0] ;
}
/**
* Method to perform dot product
*/
LONG dotProduct ( LONG a[3], LONG b[3] )
{
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] ;
}
void normalize( double a[3] )
{
double mag = a[0] * a[0] + a[1] * a[1] + a[2] * a[2] ;
if ( mag > 0 )
{
mag = sqrt( mag ) ;
a[0] /= mag ;
a[1] /= mag ;
a[2] /= mag ;
}
}
};
#endif

@ -0,0 +1,110 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Tao Ju
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef QUEUE_H
#define QUEUE_H
struct gridQueueEle
{
int x, y, z;
UCHAR dir ;
gridQueueEle* next ;
};
class GridQueue
{
gridQueueEle* head ;
gridQueueEle* tail ;
int numEles ;
public:
GridQueue( )
{
head = NULL ;
tail = NULL ;
numEles = 0 ;
}
gridQueueEle* getHead( )
{
return head ;
}
int getNumElements( )
{
return numEles ;
}
void pushQueue( int st[3], int dir )
{
gridQueueEle* ele = new gridQueueEle ;
ele->x = st[0] ;
ele->y = st[1] ;
ele->z = st[2] ;
ele->dir = (UCHAR) dir ;
ele->next = NULL ;
if ( head == NULL )
{
head = ele ;
}
else
{
tail->next = ele ;
}
tail = ele ;
numEles ++ ;
}
int popQueue( int st[3], int& dir )
{
if ( head == NULL )
{
return 0 ;
}
st[0] = head->x ;
st[1] = head->y ;
st[2] = head->z ;
dir = (int) (head->dir) ;
gridQueueEle* temp = head ;
head = head->next ;
delete temp ;
if ( head == NULL )
{
tail = NULL ;
}
numEles -- ;
return 1 ;
}
};
#endif

@ -0,0 +1,46 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Tao Ju
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef CUBES_H
#define CUBES_H
#include "marching_cubes_table.h"
/* simple wrapper for auto-generated marching cubes data */
class Cubes
{
public:
/// Get number of triangles
int getNumTriangle(int mask)
{
return marching_cubes_numtri[mask];
}
/// Get a triangle
void getTriangle(int mask, int index, int indices[3] )
{
for(int i = 0; i < 3; i++)
indices[i] = marching_cubes_tris[mask][index][i];
}
};
#endif

@ -0,0 +1,191 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Nicholas Bishop
*
* ***** END GPL LICENSE BLOCK *****
*/
#include <cassert>
#include "dualcon.h"
#include "ModelReader.h"
#include "octree.h"
#include <cstdio>
void veccopy(float dst[3], const float src[3])
{
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
}
#define GET_FACE(_mesh, _n) \
(*(DualConFaces)(((char*)(_mesh)->faces) + ((_n) * (_mesh)->face_stride)))
#define GET_CO(_mesh, _n) \
(*(DualConCo)(((char*)(_mesh)->co) + ((_n) * (_mesh)->co_stride)))
class DualConInputReader : public ModelReader
{
private:
const DualConInput *input_mesh;
int tottri, curface, offset;
float min[3], max[3], maxsize;
float scale;
public:
DualConInputReader(const DualConInput *mesh, float _scale)
: input_mesh(mesh), scale(_scale)
{
reset();
}
void reset()
{
tottri = 0;
curface = 0;
offset = 0;
maxsize = 0;
/* initialize tottri */
for(int i = 0; i < input_mesh->totface; i++)
tottri += GET_FACE(input_mesh, i)[3] ? 2 : 1;
veccopy(min, input_mesh->min);
veccopy(max, input_mesh->max);
/* initialize maxsize */
for(int i = 0; i < 3; i++) {
float d = max[i] - min[i];
if(d > maxsize)
maxsize = d;
}
/* redo the bounds */
for(int i = 0; i < 3; i++)
{
min[i] = (max[i] + min[i]) / 2 - maxsize / 2;
max[i] = (max[i] + min[i]) / 2 + maxsize / 2;
}
for(int i = 0; i < 3; i++)
min[i] -= maxsize * (1 / scale - 1) / 2;
maxsize *= 1 / scale;
}
Triangle* getNextTriangle()
{
if(curface == input_mesh->totface)
return 0;
Triangle* t = new Triangle();
unsigned int *f = GET_FACE(input_mesh, curface);
if(offset == 0) {
veccopy(t->vt[0], GET_CO(input_mesh, f[0]));
veccopy(t->vt[1], GET_CO(input_mesh, f[1]));
veccopy(t->vt[2], GET_CO(input_mesh, f[2]));
}
else {
veccopy(t->vt[0], GET_CO(input_mesh, f[2]));
veccopy(t->vt[1], GET_CO(input_mesh, f[3]));
veccopy(t->vt[2], GET_CO(input_mesh, f[0]));
}
if(offset == 0 && f[3])
offset++;
else {
offset = 0;
curface++;
}
return t;
}
int getNextTriangle(int t[3])
{
if(curface == input_mesh->totface)
return 0;
unsigned int *f = GET_FACE(input_mesh, curface);
if(offset == 0) {
t[0] = f[0];
t[1] = f[1];
t[2] = f[2];
}
else {
t[0] = f[2];
t[1] = f[3];
t[2] = f[0];
}
if(offset == 0 && f[3])
offset++;
else {
offset = 0;
curface++;
}
return 1;
}
int getNumTriangles()
{
return tottri;
}
int getNumVertices()
{
return input_mesh->totco;
}
float getBoundingBox(float origin[3])
{
veccopy(origin, min);
return maxsize ;
}
/* output */
void getNextVertex(float v[3])
{
/* not used */
}
/* stubs */
void printInfo() {}
int getMemory() { return sizeof(DualConInputReader); }
};
void *dualcon(const DualConInput *input_mesh,
/* callbacks for output */
DualConAllocOutput alloc_output,
DualConAddVert add_vert,
DualConAddQuad add_quad,
DualConFlags flags,
DualConMode mode,
float threshold,
float hermite_num,
float scale,
int depth)
{
DualConInputReader r(input_mesh, scale);
Octree o(&r, alloc_output, add_vert, add_quad,
flags, mode, depth, threshold, hermite_num);
o.scanConvert();
return o.getOutputMesh();
}

@ -0,0 +1,282 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Tao Ju
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "manifold_table.h"
const ManifoldIndices manifold_table[256] = {
{0, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
{1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}},
{2, {{0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}}},
{1, {{1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
{2, {{1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}},
{1, {{1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}},
{2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}}},
{1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
{2, {{1, 1}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}}},
{3, {{1, 1}, {2, 2}, {3, 3}, {0, 0}, {3, 3}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {3, 3}, {1, 1}, {0, 0}}},
{1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}},
{2, {{1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}}},
{2, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {0, 0}}},
{2, {{1, 1}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {2, 2}, {1, 1}, {0, 0}}},
{1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}},
{2, {{1, 1}, {0, 0}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}},
{2, {{1, 1}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}}},
{1, {{0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
{1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
{2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}},
{1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
{2, {{0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}}},
{2, {{1, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {2, 2}, {0, 0}}},
{2, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {2, 2}, {1, 1}, {2, 2}, {0, 0}}},
{1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}},
{2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}}},
{3, {{1, 1}, {2, 2}, {0, 0}, {3, 3}, {1, 1}, {3, 3}, {0, 0}, {2, 2}, {1, 1}, {3, 3}, {2, 2}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}}},
{1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}},
{2, {{0, 0}, {1, 1}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
{2, {{1, 1}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}},
{1, {{1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
{1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
{2, {{1, 1}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}},
{2, {{1, 1}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
{2, {{1, 1}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {0, 0}}},
{2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {1, 1}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {0, 0}}},
{1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
{2, {{1, 1}, {1, 1}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
{2, {{0, 0}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 2}, {2, 2}, {2, 1}, {0, 0}, {0, 0}, {0, 0}}},
{2, {{1, 1}, {0, 0}, {2, 2}, {1, 2}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 1}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
{2, {{1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}}},
{2, {{0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}}},
{2, {{1, 1}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 2}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}},
{1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}}},
{2, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}}},
{1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}},
{2, {{0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {1, 1}}},
{3, {{1, 1}, {0, 0}, {2, 2}, {3, 3}, {1, 1}, {3, 3}, {2, 2}, {0, 0}, {1, 1}, {3, 3}, {0, 0}, {2, 2}}},
{2, {{0, 0}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {2, 2}}},
{2, {{1, 1}, {1, 1}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {2, 2}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
{1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}},
{1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}},
{1, {{1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
{1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}},
{1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}}},
{2, {{1, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {1, 1}}},
{1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}},
{1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}},
{2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {1, 1}}},
{1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}}},
{2, {{1, 1}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {1, 1}}},
{2, {{0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {1, 1}}},
{2, {{1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {2, 2}, {1, 1}, {1, 1}}},
{2, {{0, 0}, {1, 2}, {1, 1}, {2, 2}, {2, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {1, 1}}},
{1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}}},
{2, {{2, 2}, {1, 1}, {0, 0}, {1, 1}, {2, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 2}}},
{1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}},
{2, {{0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {2, 2}}},
{3, {{1, 1}, {2, 2}, {3, 3}, {0, 0}, {1, 1}, {0, 0}, {3, 3}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {3, 3}}},
{2, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {2, 2}, {0, 0}, {2, 2}, {1, 1}}},
{2, {{1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {2, 2}}},
{2, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {2, 2}}},
{2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {1, 1}, {2, 2}, {1, 1}}},
{2, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {2, 2}, {1, 1}, {2, 2}, {1, 1}}},
{2, {{2, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {1, 2}, {1, 1}, {2, 2}}},
{3, {{0, 0}, {1, 1}, {2, 2}, {3, 3}, {0, 0}, {3, 3}, {2, 2}, {1, 1}, {0, 0}, {3, 3}, {1, 1}, {2, 2}}},
{4, {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 1}, {4, 4}, {3, 3}, {2, 2}, {1, 1}, {4, 4}, {2, 2}, {3, 3}}},
{2, {{0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 1}}},
{2, {{1, 1}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {2, 2}}},
{2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {2, 2}}},
{2, {{1, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {1, 1}}},
{2, {{0, 0}, {0, 0}, {0, 0}, {2, 1}, {1, 1}, {0, 0}, {1, 1}, {2, 2}, {1, 2}, {0, 0}, {2, 2}, {1, 1}}},
{2, {{1, 2}, {0, 0}, {0, 0}, {2, 1}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {2, 2}, {1, 1}}},
{1, {{1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
{1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}},
{1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}},
{1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
{1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}},
{1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {1, 1}}},
{2, {{2, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {1, 2}, {2, 2}, {1, 1}, {0, 0}, {1, 1}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}},
{2, {{1, 1}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}}},
{2, {{0, 0}, {1, 1}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {1, 1}}},
{2, {{1, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {2, 1}, {1, 1}, {1, 1}, {0, 0}, {2, 2}}},
{2, {{0, 0}, {0, 0}, {2, 2}, {1, 1}, {1, 2}, {0, 0}, {0, 0}, {2, 1}, {0, 0}, {1, 1}, {0, 0}, {2, 2}}},
{2, {{1, 1}, {1, 1}, {0, 0}, {2, 2}, {1, 2}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {2, 1}}},
{2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {1, 2}, {0, 0}, {0, 0}, {2, 1}}},
{2, {{1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
{2, {{1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}}},
{2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}}},
{2, {{1, 1}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {2, 2}}},
{2, {{0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}}},
{2, {{1, 1}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 2}}},
{3, {{0, 0}, {1, 1}, {2, 2}, {3, 3}, {2, 2}, {1, 1}, {0, 0}, {3, 3}, {1, 1}, {2, 2}, {0, 0}, {3, 3}}},
{2, {{1, 1}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}},
{2, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {2, 2}}},
{1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {1, 1}}},
{1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}},
{1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
{1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}},
{1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}},
{1, {{1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
{2, {{1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}}},
{2, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}}},
{3, {{1, 1}, {2, 2}, {0, 0}, {3, 3}, {0, 0}, {2, 2}, {1, 1}, {3, 3}, {2, 2}, {0, 0}, {1, 1}, {3, 3}}},
{2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}}},
{3, {{1, 1}, {0, 0}, {2, 2}, {3, 3}, {2, 2}, {0, 0}, {1, 1}, {3, 3}, {0, 0}, {2, 2}, {1, 1}, {3, 3}}},
{2, {{0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {1, 1}, {1, 1}, {2, 2}}},
{4, {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {3, 3}, {2, 2}, {1, 1}, {4, 4}, {2, 2}, {3, 3}, {1, 1}, {4, 4}}},
{2, {{0, 0}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 2}}},
{2, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {2, 2}}},
{2, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {1, 1}, {2, 2}}},
{2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {2, 2}, {1, 1}, {2, 2}}},
{2, {{0, 0}, {2, 1}, {0, 0}, {0, 0}, {1, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {1, 1}, {2, 2}, {1, 1}}},
{2, {{1, 1}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}}},
{2, {{0, 0}, {0, 0}, {2, 1}, {0, 0}, {0, 0}, {1, 2}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {1, 1}, {2, 2}}},
{2, {{1, 1}, {2, 2}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {0, 0}, {1, 1}, {2, 2}}},
{2, {{0, 0}, {1, 2}, {2, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}}},
{1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}},
{2, {{1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {2, 2}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}}},
{1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}},
{2, {{0, 0}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {1, 1}}},
{2, {{1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {2, 2}}},
{2, {{0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {2, 2}}},
{2, {{1, 1}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 2}, {2, 2}}},
{1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}}},
{2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {2, 2}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}},
{1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}}},
{1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}},
{2, {{2, 2}, {1, 1}, {1, 2}, {0, 0}, {0, 0}, {2, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {1, 1}}},
{1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}}},
{1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}},
{1, {{1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
{1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}},
{1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
{2, {{1, 1}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {1, 1}}},
{2, {{0, 0}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 1}, {0, 0}, {1, 2}, {2, 2}, {0, 0}, {1, 1}}},
{2, {{1, 1}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {1, 1}}},
{2, {{0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {1, 2}, {2, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {1, 1}}},
{1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}},
{2, {{0, 0}, {2, 1}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {1, 2}}},
{1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}},
{2, {{2, 2}, {1, 2}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 1}}},
{2, {{0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}}},
{2, {{2, 2}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 2}, {0, 0}, {0, 0}, {2, 1}}},
{1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
{1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
{2, {{1, 1}, {0, 0}, {2, 2}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
{2, {{0, 0}, {1, 1}, {2, 2}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
{2, {{1, 1}, {1, 1}, {2, 2}, {2, 2}, {1, 1}, {1, 1}, {2, 2}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
{1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}},
{2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {2, 2}, {1, 1}, {2, 2}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}}},
{2, {{1, 2}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 1}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
{2, {{1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}},
{2, {{1, 1}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 2}, {0, 0}, {2, 1}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}},
{2, {{1, 1}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}}},
{2, {{0, 0}, {1, 1}, {1, 2}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {2, 1}, {0, 0}}},
{1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}}},
{2, {{1, 1}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {1, 1}, {0, 0}}},
{2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 2}, {2, 1}, {0, 0}}},
{1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}},
{2, {{0, 0}, {0, 0}, {2, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {1, 2}, {0, 0}}},
{2, {{1, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 1}, {2, 2}, {1, 2}, {1, 1}, {0, 0}}},
{2, {{0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}}},
{1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}},
{2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 2}, {0, 0}, {0, 0}, {2, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}}},
{1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
{1, {{0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
{2, {{1, 1}, {2, 2}, {2, 2}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}},
{2, {{2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {1, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {2, 1}, {0, 0}}},
{1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}},
{2, {{1, 1}, {2, 2}, {0, 0}, {1, 2}, {0, 0}, {0, 0}, {2, 1}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {0, 0}}},
{2, {{0, 0}, {0, 0}, {0, 0}, {2, 1}, {2, 2}, {1, 1}, {1, 2}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {0, 0}}},
{2, {{1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}}},
{1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}},
{2, {{1, 1}, {2, 2}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}}},
{2, {{1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {2, 1}, {1, 2}, {0, 0}}},
{1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
{2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {1, 2}, {2, 1}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}},
{1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
{1, {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}},
{2, {{1, 2}, {0, 0}, {0, 0}, {2, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
{1, {{1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
{2, {{0, 0}, {1, 2}, {2, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}}},
{1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
{1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
{1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
{0, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}}
};

@ -0,0 +1,33 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Tao Ju
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef MANIFOLD_TABLE_H
#define MANIFOLD_TABLE_H
typedef struct {
int comps;
int pairs[12][2];
} ManifoldIndices;
extern const ManifoldIndices manifold_table[256];
#endif

@ -0,0 +1,554 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Tao Ju
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "marching_cubes_table.h"
/* number of triangles in each configuration */
const int marching_cubes_numtri[TOTCONF] = {
0, 1, 1, 2, 1, 2, 4, 3, 1, 4, 2, 3, 2, 3, 3, 2, 1, 2, 4, 3, 4, 3, 5, 4,
6, 5, 5, 4, 5, 4, 4, 3, 1, 4, 2, 3, 6, 5, 5, 4, 4, 5, 3, 4, 5, 4, 4, 3,
2, 3, 3, 2, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 1, 4, 6, 5, 2, 3, 5, 4,
4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 2, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2,
4, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 3, 4, 4, 3, 4, 3, 3, 2,
4, 3, 3, 2, 3, 2, 2, 1, 1, 6, 4, 5, 4, 5, 5, 4, 2, 5, 3, 4, 3, 4, 4, 3,
4, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 2, 5, 3, 4, 5, 4, 4, 3,
3, 4, 2, 3, 4, 3, 3, 2, 3, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1,
2, 5, 5, 4, 3, 4, 4, 3, 3, 4, 4, 3, 2, 3, 3, 2, 3, 4, 4, 3, 4, 3, 3, 2,
4, 3, 3, 2, 3, 2, 2, 1, 3, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1,
2, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0
};
/* table of triangles in each configuration */
const int marching_cubes_tris[TOTCONF][MAX_TRIS][3] = {
{{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,0,8}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,1,5}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,0,1}, {4,1,5}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,9,2}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,8,9}, {0,9,2}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{1,5,9}, {1,9,2}, {1,2,4}, {1,4,8}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,1,5}, {0,5,9}, {0,9,2}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,3,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,8,5}, {0,5,3}, {0,3,9}, {0,9,4}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,1,3}, {8,3,9}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,0,1}, {4,1,3}, {4,3,9}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,5,3}, {4,3,2}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,8,5}, {0,5,3}, {0,3,2}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,1}, {4,1,3}, {4,3,2}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,1,3}, {0,3,2}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,6,10}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,4,6}, {8,6,10}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,10,1}, {6,1,5}, {6,5,8}, {6,8,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,6,10}, {4,10,1}, {4,1,5}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,0,4}, {10,4,9}, {10,9,2}, {10,2,6}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,10,8}, {6,8,9}, {6,9,2}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,0}, {6,10,1}, {6,1,5}, {6,5,9}, {6,9,2},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,10,1}, {6,1,5}, {6,5,9}, {6,9,2}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,0,5}, {0,6,9}, {9,5,0}, {6,10,3}, {5,3,10},
{3,9,6}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,8,5}, {10,5,3}, {9,4,6}, {6,10,3}, {6,3,9},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,1,3}, {9,8,0}, {9,0,6}, {6,10,3}, {6,3,9},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,6,10}, {4,10,1}, {4,1,3}, {4,3,9}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,4,5}, {3,2,6}, {3,6,10}, {10,0,5}, {10,5,3},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,10,8}, {6,8,5}, {6,5,3}, {6,3,2}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,0}, {6,10,1}, {6,1,3}, {6,3,2}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,10,1}, {6,1,3}, {6,3,2}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,7,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,0,10}, {4,10,7}, {4,7,1}, {4,1,8}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,10,7}, {8,7,5}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,0,10}, {4,10,7}, {4,7,5}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,2,4}, {10,4,1}, {7,2,10}, {1,9,7}, {1,4,9},
{9,2,7}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{1,8,9}, {2,0,10}, {2,10,7}, {7,1,9}, {7,9,2},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,10}, {7,5,9}, {7,9,2}, {2,4,10}, {2,10,7},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,10,7}, {0,7,5}, {0,5,9}, {0,9,2}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,7,3}, {10,3,9}, {10,9,5}, {10,5,1}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,5,1}, {4,0,10}, {4,10,7}, {4,7,3}, {4,3,9},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,10,7}, {8,7,3}, {8,3,9}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,0,10}, {4,10,7}, {4,7,3}, {4,3,9}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,5,1}, {4,1,10}, {7,3,2}, {2,4,10}, {2,10,7},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,5,1}, {0,10,7}, {0,7,3}, {0,3,2}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,10}, {4,10,7}, {4,7,3}, {4,3,2}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,10,7}, {0,7,3}, {0,3,2}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,6,7}, {0,7,1}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,4,6}, {8,6,7}, {8,7,1}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,0,6}, {8,6,7}, {8,7,5}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,6,7}, {4,7,5}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{1,0,4}, {1,4,9}, {2,6,7}, {7,1,9}, {7,9,2},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,7,1}, {6,1,8}, {6,8,9}, {6,9,2}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,0}, {6,7,5}, {6,5,9}, {6,9,2}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,7,5}, {6,5,9}, {6,9,2}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,1,0}, {6,7,3}, {6,3,9}, {9,5,0}, {9,0,6},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,5,1}, {4,6,7}, {4,7,3}, {4,3,9}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,0,6}, {8,6,7}, {8,7,3}, {8,3,9}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,6,7}, {4,7,3}, {4,3,9}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,4,5}, {0,5,1}, {6,7,3}, {6,3,2}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,5,1}, {6,7,3}, {6,3,2}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,0}, {6,7,3}, {6,3,2}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,7,3}, {6,3,2}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,2,11}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,4,2}, {8,2,11}, {8,11,6}, {8,6,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,1,6}, {6,1,11}, {11,1,5}, {2,11,5}, {2,5,8},
{6,2,8}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,0,1}, {5,4,2}, {5,2,11}, {11,6,1}, {11,1,5},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,4,9}, {6,9,11}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,0,8}, {6,8,9}, {6,9,11}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,4,8}, {6,8,1}, {5,9,11}, {11,6,1}, {11,1,5},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,0,1}, {6,1,5}, {6,5,9}, {6,9,11}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,2,9}, {6,9,5}, {6,5,3}, {6,3,11}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,2,9}, {6,0,8}, {6,8,5}, {6,5,3}, {6,3,11},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{2,9,8}, {1,3,11}, {1,11,6}, {6,2,8}, {6,8,1},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,2,9}, {6,0,1}, {6,1,3}, {6,3,11}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,4,5}, {6,5,3}, {6,3,11}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,0,8}, {6,8,5}, {6,5,3}, {6,3,11}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,4,8}, {6,8,1}, {6,1,3}, {6,3,11}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,0,1}, {6,1,3}, {6,3,11}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,0,2}, {10,2,11}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,8,4}, {10,4,2}, {10,2,11}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,0,2}, {11,10,1}, {11,1,5}, {5,8,2}, {5,2,11},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,1,5}, {10,5,4}, {10,4,2}, {10,2,11}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,0,4}, {10,4,9}, {10,9,11}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,8,9}, {10,9,11}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,0}, {10,1,5}, {10,5,9}, {10,9,11}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,1,5}, {10,5,9}, {10,9,11}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,2,9}, {0,9,5}, {3,11,10}, {10,0,5}, {10,5,3},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,2,9}, {10,8,5}, {10,5,3}, {10,3,11}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,0,2}, {8,2,9}, {10,1,3}, {10,3,11}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,2,9}, {10,1,3}, {10,3,11}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,0,4}, {10,4,5}, {10,5,3}, {10,3,11}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,8,5}, {10,5,3}, {10,3,11}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,0}, {10,1,3}, {10,3,11}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,1,3}, {10,3,11}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{1,10,6}, {1,6,2}, {1,2,11}, {1,11,7}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,10,6}, {7,1,8}, {7,8,4}, {7,4,2}, {7,2,11},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,10,6}, {8,6,2}, {11,7,5}, {5,8,2}, {5,2,11},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,10,6}, {7,5,4}, {7,4,2}, {7,2,11}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,6,4}, {9,11,7}, {9,7,1}, {1,10,4}, {1,4,9},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,10,6}, {7,1,8}, {7,8,9}, {7,9,11}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,10}, {4,10,6}, {7,5,9}, {7,9,11}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,10,6}, {7,5,9}, {7,9,11}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,1,10}, {5,10,6}, {5,6,2}, {5,2,9}, {7,3,11},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,10,6}, {8,5,1}, {4,2,9}, {7,3,11}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,10,6}, {8,6,2}, {8,2,9}, {7,3,11}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,10,6}, {4,2,9}, {7,3,11}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,6,4}, {10,4,5}, {10,5,1}, {7,3,11}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,10,6}, {8,5,1}, {7,3,11}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,10}, {4,10,6}, {7,3,11}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,10,6}, {7,3,11}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{7,1,0}, {7,0,2}, {7,2,11}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{7,1,8}, {7,8,4}, {7,4,2}, {7,2,11}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{7,5,8}, {7,8,0}, {7,0,2}, {7,2,11}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{7,5,4}, {7,4,2}, {7,2,11}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{7,1,0}, {7,0,4}, {7,4,9}, {7,9,11}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{7,1,8}, {7,8,9}, {7,9,11}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,0}, {7,5,9}, {7,9,11}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{7,5,9}, {7,9,11}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,1,0}, {5,0,2}, {5,2,9}, {7,3,11}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,5,1}, {4,2,9}, {7,3,11}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,0,2}, {8,2,9}, {7,3,11}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,2,9}, {7,3,11}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,4,5}, {0,5,1}, {7,3,11}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,5,1}, {7,3,11}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,0}, {7,3,11}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{7,3,11}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{7,11,3}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{7,11,0}, {7,0,8}, {0,11,4}, {8,3,7}, {11,3,4},
{3,8,4}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,1,7}, {8,7,11}, {8,11,3}, {8,3,5}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,1,7}, {0,7,11}, {3,5,4}, {4,0,11}, {4,11,3},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,9,3}, {4,3,7}, {4,7,11}, {4,11,2}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,9,3}, {8,3,7}, {11,2,0}, {0,8,7}, {0,7,11},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,9,3}, {4,8,1}, {4,1,7}, {4,7,11}, {4,11,2},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,9,3}, {0,1,7}, {0,7,11}, {0,11,2}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,7,11}, {5,11,9}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,5,7}, {11,9,4}, {11,4,0}, {0,8,7}, {0,7,11},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,1,7}, {8,7,11}, {8,11,9}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,0,1}, {4,1,7}, {4,7,11}, {4,11,9}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,5,7}, {4,7,11}, {4,11,2}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,8,5}, {0,5,7}, {0,7,11}, {0,11,2}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,1}, {4,1,7}, {4,7,11}, {4,11,2}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,1,7}, {0,7,11}, {0,11,2}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,6,11}, {0,11,3}, {0,3,7}, {0,7,10}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{7,10,8}, {4,6,11}, {4,11,3}, {3,7,8}, {3,8,4},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,1,7}, {5,8,0}, {5,0,6}, {5,6,11}, {5,11,3},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,1,7}, {5,4,6}, {5,6,11}, {5,11,3}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{7,10,0}, {7,0,4}, {7,4,9}, {7,9,3}, {6,11,2},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{7,10,8}, {7,8,9}, {7,9,3}, {6,11,2}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,0}, {10,1,7}, {5,9,3}, {6,11,2}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,1,7}, {5,9,3}, {6,11,2}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,7,10}, {5,10,0}, {6,11,9}, {9,5,0}, {9,0,6},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,8,5}, {10,5,7}, {4,6,11}, {4,11,9}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,1,7}, {8,0,6}, {8,6,11}, {8,11,9}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,1,7}, {4,6,11}, {4,11,9}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,0,4}, {10,4,5}, {10,5,7}, {6,11,2}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,8,5}, {10,5,7}, {6,11,2}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,0}, {10,1,7}, {6,11,2}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,1,7}, {6,11,2}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{1,10,11}, {1,11,3}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,10,11}, {3,1,8}, {3,8,4}, {4,0,11}, {4,11,3},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,8,10}, {5,10,11}, {5,11,3}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,4,0}, {5,0,10}, {5,10,11}, {5,11,3}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{9,3,1}, {10,11,2}, {10,2,4}, {4,9,1}, {4,1,10},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{1,8,9}, {1,9,3}, {0,10,11}, {0,11,2}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,9,3}, {4,8,10}, {4,10,11}, {4,11,2}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,9,3}, {0,10,11}, {0,11,2}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,1,10}, {5,10,11}, {5,11,9}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,5,1}, {4,0,10}, {4,10,11}, {4,11,9}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,10,11}, {8,11,9}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,0,10}, {4,10,11}, {4,11,9}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,5,1}, {4,1,10}, {4,10,11}, {4,11,2}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,5,1}, {0,10,11}, {0,11,2}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,10}, {4,10,11}, {4,11,2}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,10,11}, {0,11,2}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{1,0,6}, {1,6,11}, {1,11,3}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{1,8,4}, {1,4,6}, {1,6,11}, {1,11,3}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,8,0}, {5,0,6}, {5,6,11}, {5,11,3}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,4,6}, {5,6,11}, {5,11,3}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{1,0,4}, {1,4,9}, {1,9,3}, {6,11,2}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{1,8,9}, {1,9,3}, {6,11,2}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,0}, {5,9,3}, {6,11,2}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,9,3}, {6,11,2}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,1,0}, {5,0,6}, {5,6,11}, {5,11,9}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,5,1}, {4,6,11}, {4,11,9}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,0,6}, {8,6,11}, {8,11,9}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,6,11}, {4,11,9}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,4,5}, {0,5,1}, {6,11,2}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,5,1}, {6,11,2}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,0}, {6,11,2}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,11,2}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{7,6,2}, {7,2,3}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{7,6,0}, {7,0,8}, {4,2,3}, {3,7,8}, {3,8,4},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{1,7,6}, {2,3,5}, {2,5,8}, {8,1,6}, {8,6,2},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,0,1}, {6,1,7}, {5,4,2}, {5,2,3}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{7,6,4}, {7,4,9}, {7,9,3}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{7,6,0}, {7,0,8}, {7,8,9}, {7,9,3}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,4,8}, {6,8,1}, {6,1,7}, {5,9,3}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,0,1}, {6,1,7}, {5,9,3}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,7,6}, {5,6,2}, {5,2,9}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,0,8}, {6,8,5}, {6,5,7}, {4,2,9}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,1,7}, {8,7,6}, {8,6,2}, {8,2,9}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,0,1}, {6,1,7}, {4,2,9}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,4,5}, {6,5,7}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,0,8}, {6,8,5}, {6,5,7}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,4,8}, {6,8,1}, {6,1,7}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{6,0,1}, {6,1,7}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{7,10,0}, {7,0,2}, {7,2,3}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{7,10,8}, {7,8,4}, {7,4,2}, {7,2,3}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,1,7}, {5,8,0}, {5,0,2}, {5,2,3}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,1,7}, {5,4,2}, {5,2,3}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{7,10,0}, {7,0,4}, {7,4,9}, {7,9,3}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{7,10,8}, {7,8,9}, {7,9,3}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,0}, {10,1,7}, {5,9,3}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,1,7}, {5,9,3}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,7,10}, {5,10,0}, {5,0,2}, {5,2,9}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,8,5}, {10,5,7}, {4,2,9}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,1,7}, {8,0,2}, {8,2,9}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,1,7}, {4,2,9}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,0,4}, {10,4,5}, {10,5,7}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,8,5}, {10,5,7}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,0}, {10,1,7}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,1,7}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{1,10,6}, {1,6,2}, {1,2,3}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,10,6}, {1,8,4}, {1,4,2}, {1,2,3}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,8,10}, {5,10,6}, {5,6,2}, {5,2,3}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,10,6}, {5,4,2}, {5,2,3}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{1,10,6}, {1,6,4}, {1,4,9}, {1,9,3}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,10,6}, {1,8,9}, {1,9,3}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,10}, {4,10,6}, {5,9,3}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,10,6}, {5,9,3}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,1,10}, {5,10,6}, {5,6,2}, {5,2,9}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,10,6}, {8,5,1}, {4,2,9}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,10,6}, {8,6,2}, {8,2,9}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,10,6}, {4,2,9}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{10,6,4}, {10,4,5}, {10,5,1}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,10,6}, {8,5,1}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,10}, {4,10,6}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,10,6}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{1,0,2}, {1,2,3}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{1,8,4}, {1,4,2}, {1,2,3}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,8,0}, {5,0,2}, {5,2,3}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,4,2}, {5,2,3}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{1,0,4}, {1,4,9}, {1,9,3}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{1,8,9}, {1,9,3}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,0}, {5,9,3}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,9,3}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{5,1,0}, {5,0,2}, {5,2,9}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,5,1}, {4,2,9}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,0,2}, {8,2,9}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,2,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,4,5}, {0,5,1}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{8,5,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{4,8,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
{{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},
{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}}
};

@ -0,0 +1,38 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Tao Ju
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef MARCHING_CUBES_TABLE_H
#define MARCHING_CUBES_TABLE_H
/* number of configurations */
#define TOTCONF 256
/* maximum number of triangles per configuration */
#define MAX_TRIS 10
/* number of triangles in each configuration */
extern const int marching_cubes_numtri[TOTCONF];
/* table of triangles in each configuration */
extern const int marching_cubes_tris[TOTCONF][MAX_TRIS][3];
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,112 @@
PolyMender program for robustly repairing a polygonal model.
Author: Tao Ju (jutao@cs.wustl.edu)
Version: 1.6 (Updated: Oct. 12, 2006)
Platform: Windows
I. What's new in v1.6:
> Removal of disconnected components
> Topologically manifold dual contouring
> Output signed octree with geometry
II. Introduction
PolyMender is based on the algorithm presented in the paper "Robust Repair of Polygonal Models" (SIGGRAPH 2004). The program reads in a polygonal model (i.e., a bag of polygons) and produces a closed surface that approximates the original model. PolyMender consumes a small amount of time and memory space, and can accurately reproduce the original geometry. PolyMender is suitable for repairing CAD models and gigantic polygonal models. Alternatively, PolyMender can also be used to generate a signed volume from any polygonal models.
III. How to run
The executable package contains three programs:
1. PolyMender, PolyMender-clean
Purpose: repairs general purpose models, such as those created from range scanners. The repaired surface is constructed using Marching Cubes. Consumes minimal memory and time and generates closed, manifold triangular surfaces. The -clean option removes isolated pieces.
2. PolyMender-qd, PolyMender-qd-clean
Purpose: same as PolyMender and PolyMender-clean, but outputs a quad-mesh.
3. PolyMender-dc, PolyMender-dc-clean
Purpose: repairs models containing sharp features, such as CAD models. The repaired surface is constructed using Dual Contouring with a manifold topology, which is capable of reproducing sharp edges and corners. However, more memory is required. Generates closed triangular and quadrilateral surfaces. The -clean option removes isolated pieces.
Type the program names (e.g., PolyMender) on the DOS prompt and you will see their usages:
Usage: PolyMender <input_file> <octree_depth> <scale> <output_file>
Example: PolyMender bunny.ply 6 0.9 closedbunny.ply
Description:
<input_file> Polygonal file of format STL (binary only), ASC, or PLY.
<octree_depth> Integer depth of octree. The dimension of the volumetric
grid is 2^<octree_depth> on each side.
<scale> Floating point number between 0 and 1 denoting the ratio of
the largest dimension of the model over the size of the grid.
<output_file> Output in polygonal format PLY or signed-octree format SOF (or SOG).
Additional notes:
1. STL(binary) is preferred input format, since the program does not need to store the model in memory at all. ASC or PLY formats require additional storage of vertices, due to their topology-geometry file structure.
2. The running time and memory consumption of the program depends on several factors: the number of input polygons, the depth of the octree, and the surface area of the model (hence the number of leaf nodes on the octree). To give an idea, processing the David model with 56 million triangles at depth 13 takes 45 minutes using 500 MB RAM (excluding the mem allocated for storing vertices when reading PLY format) on a PC with AMD 1.5Hz CPU.
3. The number of output polygons can be finely controlled using the scale argument. The large the scale, the more polygons are generated, since the model occupies a larger portion of the volume grid.
4. As an alternative of output repaired models, the intermediate signed octree can be generated as a SOF or SOG file. The signed octree can be used for generating signed distance field, extracting isosurfaces, or multiresolution spatial representation of the polygonal model.
IV SOF format
SOF (Signed Octree Format) records an octree grid with signes attached to the 8 corners of each leaf node. All leaf nodes appear at the same depth that is specified by the <octree_depth> argument to the program. The tree is recorded in SOF file using pre-order traversal. Here is the structure of a SOF file (binary):
<header>
<node>
<header> is a 4-bytes integer that equals 2 ^ octree_depth. The first byte of a <node> is either 0 (denoting an intermediate node) or 1 (denoting an empty node) or 2 (denoting a leaf node). After the first byte, an intermediate node <node> contains (after the first byte) eight <node> structures for its eight children; an empty node <node> contains one byte of value 0 or 1 denoting if it is inside or outside; and a leaf node contains one byte whose eight bits correspond to the signs at its eight corners (0 for inside and 1 for outside). The order of enumeration of the eight children nodes in an intermediate nodeis the following (expressed in coordinates <x,y,z> ): <0,0,0>,<0,0,1>,<0,1,0>,<0,1,1>,<1,0,0>,<1,0,1>,<1,1,0>,<1,1,1>. The enumeration of the eight corners in a leaf node follows the same order (e.g., the lowest bit records the sign at <0,0,0>).
V SOG format
SOF (Signed Octree with Geometry) has the same data structure with SOG, with the addition of following features:
1. The file starts with a 128-byte long header. Currently, the header begins with the string "SOG.Format 1.0" followed by 3 floats representing the lower-left-near corner of the octree follwed by 1 float denoting the length of the octree (in one direction). The locations and lengths are in the input model's coordinate space. The rest of the header is left empty.
2. Each leaf node has additioanl three floats {x,y,z} (following the signs) denoting the geometric location of a feature vertex within the cell.
VI Test data
Three models are included in the testmodels package. (Suggested arguments are provided in the parathesis).
bunny.ply (octree depth: 7, scale: 0.9)
- The Stanford Bunny (containing big holes at the bottom)
horse.stl (octree depth: 8, scale: 0.9)
- The horse model with 1/3 of all polygons removed and vertices randomly perturbed.
mechanic.asc (octree depth: 6, scale: 0.9)
- A mechanic part with hanging triangles

@ -579,7 +579,8 @@ GHOST_TSuccess GHOST_SystemCarbon::getButtons(GHOST_Buttons& buttons) const
static bool g_hasFirstFile = false; static bool g_hasFirstFile = false;
static char g_firstFileBuf[512]; static char g_firstFileBuf[512];
extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) { extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG])
{
if (g_hasFirstFile) { if (g_hasFirstFile) {
strncpy(buf, g_firstFileBuf, FIRSTFILEBUFLG - 1); strncpy(buf, g_firstFileBuf, FIRSTFILEBUFLG - 1);
buf[FIRSTFILEBUFLG - 1] = '\0'; buf[FIRSTFILEBUFLG - 1] = '\0';

@ -451,7 +451,8 @@ static bool g_hasFirstFile = false;
static char g_firstFileBuf[512]; static char g_firstFileBuf[512];
//TODO:Need to investigate this. Function called too early in creator.c to have g_hasFirstFile == true //TODO:Need to investigate this. Function called too early in creator.c to have g_hasFirstFile == true
extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) { extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG])
{
if (g_hasFirstFile) { if (g_hasFirstFile) {
strncpy(buf, g_firstFileBuf, FIRSTFILEBUFLG - 1); strncpy(buf, g_firstFileBuf, FIRSTFILEBUFLG - 1);
buf[FIRSTFILEBUFLG - 1] = '\0'; buf[FIRSTFILEBUFLG - 1] = '\0';

@ -296,7 +296,8 @@ findGhostWindow(
} }
static void SleepTillEvent(Display *display, GHOST_TInt64 maxSleep) { static void SleepTillEvent(Display *display, GHOST_TInt64 maxSleep)
{
int fd = ConnectionNumber(display); int fd = ConnectionNumber(display);
fd_set fds; fd_set fds;

@ -70,7 +70,8 @@ const EventTypeSpec kWEvents[] = {
{ kEventClassWindow, kEventWindowZoom }, /* for new zoom behaviour */ { kEventClassWindow, kEventWindowZoom }, /* for new zoom behaviour */
}; };
static OSStatus myWEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData) { static OSStatus myWEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData)
{
WindowRef mywindow; WindowRef mywindow;
GHOST_WindowCarbon *ghost_window; GHOST_WindowCarbon *ghost_window;
OSStatus err; OSStatus err;

@ -1269,7 +1269,8 @@ GHOST_TSuccess GHOST_WindowWin32::endProgressBar()
/* Ron Fosner's code for weighting pixel formats and forcing software. /* Ron Fosner's code for weighting pixel formats and forcing software.
See http://www.opengl.org/resources/faq/technical/weight.cpp */ See http://www.opengl.org/resources/faq/technical/weight.cpp */
static int WeightPixelFormat(PIXELFORMATDESCRIPTOR& pfd) { static int WeightPixelFormat(PIXELFORMATDESCRIPTOR& pfd)
{
int weight = 0; int weight = 0;
/* assume desktop color depth is 32 bits per pixel */ /* assume desktop color depth is 32 bits per pixel */
@ -1302,7 +1303,8 @@ static int WeightPixelFormat(PIXELFORMATDESCRIPTOR& pfd) {
/* A modification of Ron Fosner's replacement for ChoosePixelFormat */ /* A modification of Ron Fosner's replacement for ChoosePixelFormat */
/* returns 0 on error, else returns the pixel format number to be used */ /* returns 0 on error, else returns the pixel format number to be used */
static int EnumPixelFormats(HDC hdc) { static int EnumPixelFormats(HDC hdc)
{
int iPixelFormat; int iPixelFormat;
int i, n, w, weight = 0; int i, n, w, weight = 0;
PIXELFORMATDESCRIPTOR pfd; PIXELFORMATDESCRIPTOR pfd;

@ -472,7 +472,8 @@ GHOST_WindowX11(
is configured but not plugged in. is configured but not plugged in.
*/ */
static int ApplicationErrorHandler(Display *display, XErrorEvent *theEvent) { static int ApplicationErrorHandler(Display *display, XErrorEvent *theEvent)
{
fprintf(stderr, "Ignoring Xlib error: error code %d request code %d\n", fprintf(stderr, "Ignoring Xlib error: error code %d request code %d\n",
theEvent->error_code, theEvent->request_code) ; theEvent->error_code, theEvent->request_code) ;

@ -94,7 +94,9 @@ typedef unsigned long uintptr_t;
#include <stdint.h> #include <stdint.h>
/* XXX */ /* XXX */
#ifndef uint64_t
#ifndef UINT64_MAX
# define UINT64_MAX 18446744073709551615
typedef uint8_t u_int8_t; typedef uint8_t u_int8_t;
typedef uint16_t u_int16_t; typedef uint16_t u_int16_t;
typedef uint32_t u_int32_t; typedef uint32_t u_int32_t;

@ -211,7 +211,8 @@ extern "C" void smoke_initWaveletBlenderRNA(WTURBULENCE *wt, float *strength)
wt->initBlenderRNA(strength); wt->initBlenderRNA(strength);
} }
template < class T > inline T ABS( T a ) { template < class T > inline T ABS( T a )
{
return (0 < a) ? a : -a ; return (0 < a) ? a : -a ;
} }

@ -62,7 +62,8 @@ int plugin_seq_getversion(void) { return B_PLUGIN_VERSION;}
void plugin_but_changed(int but) {} void plugin_but_changed(int but) {}
void plugin_init() {} void plugin_init() {}
void plugin_getinfo(PluginInfo *info) { void plugin_getinfo(PluginInfo *info)
{
info->name= name; info->name= name;
info->nvars= sizeof(varstr)/sizeof(VarStruct); info->nvars= sizeof(varstr)/sizeof(VarStruct);
info->cfra= &cfra; info->cfra= &cfra;

@ -62,7 +62,8 @@ int plugin_seq_getversion(void) { return B_PLUGIN_VERSION;}
void plugin_but_changed(int but) {} void plugin_but_changed(int but) {}
void plugin_init() {} void plugin_init() {}
void plugin_getinfo(PluginInfo *info) { void plugin_getinfo(PluginInfo *info)
{
info->name= name; info->name= name;
info->nvars= sizeof(varstr)/sizeof(VarStruct); info->nvars= sizeof(varstr)/sizeof(VarStruct);
info->cfra= &cfra; info->cfra= &cfra;
@ -74,7 +75,8 @@ void plugin_getinfo(PluginInfo *info) {
info->callback= plugin_but_changed; info->callback= plugin_but_changed;
} }
static void rgb_to_yuv(float rgb[3], float yuv[3]) { static void rgb_to_yuv(float rgb[3], float yuv[3])
{
yuv[0]= 0.299*rgb[0] + 0.587*rgb[1] + 0.114*rgb[2]; yuv[0]= 0.299*rgb[0] + 0.587*rgb[1] + 0.114*rgb[2];
yuv[1]= 0.492*(rgb[2] - yuv[0]); yuv[1]= 0.492*(rgb[2] - yuv[0]);
yuv[2]= 0.877*(rgb[0] - yuv[0]); yuv[2]= 0.877*(rgb[0] - yuv[0]);
@ -84,7 +86,8 @@ static void rgb_to_yuv(float rgb[3], float yuv[3]) {
yuv[2] /= 0.615; yuv[2] /= 0.615;
} }
static void yuv_to_rgb(float yuv[3], float rgb[3]) { static void yuv_to_rgb(float yuv[3], float rgb[3])
{
yuv[1] *= 0.436; yuv[1] *= 0.436;
yuv[2] *= 0.615; yuv[2] *= 0.615;

@ -90,7 +90,8 @@ void plugin_seq_free_private_data(void * data)
free(d); free(d);
} }
void plugin_getinfo(PluginInfo *info) { void plugin_getinfo(PluginInfo *info)
{
info->name= name; info->name= name;
info->nvars= sizeof(varstr)/sizeof(VarStruct); info->nvars= sizeof(varstr)/sizeof(VarStruct);
info->cfra= &cfra; info->cfra= &cfra;

@ -67,7 +67,8 @@ int plugin_seq_getversion(void) { return B_PLUGIN_VERSION; }
void plugin_but_changed(int but) {} void plugin_but_changed(int but) {}
void plugin_init() {} void plugin_init() {}
void plugin_getinfo(PluginInfo *info) { void plugin_getinfo(PluginInfo *info)
{
info->name= name; info->name= name;
info->nvars= sizeof(varstr)/sizeof(VarStruct); info->nvars= sizeof(varstr)/sizeof(VarStruct);
info->cfra= &cfra; info->cfra= &cfra;

@ -349,6 +349,14 @@ def preset_paths(subdir):
raise Exception("invalid subdir given %r" % subdir) raise Exception("invalid subdir given %r" % subdir)
elif _os.path.isdir(directory): elif _os.path.isdir(directory):
dirs.append(directory) dirs.append(directory)
# Find addons preset paths
import addon_utils
for path in addon_utils.paths():
directory = _os.path.join(path, "presets", subdir)
if _os.path.isdir(directory):
dirs.append(directory)
return dirs return dirs

@ -94,6 +94,16 @@ def write_sysinfo(op):
output.write('autosave: {}\n'.format(bpy.utils.user_resource('AUTOSAVE'))) output.write('autosave: {}\n'.format(bpy.utils.user_resource('AUTOSAVE')))
output.write('tempdir: {}\n'.format(bpy.app.tempdir)) output.write('tempdir: {}\n'.format(bpy.app.tempdir))
output.write('\nFFmpeg:\n')
output.write(lilies)
ffmpeg = bpy.app.ffmpeg
if ffmpeg.supported:
for lib in ['avcodec', 'avdevice', 'avformat', 'avutil', 'swscale']:
output.write('{}:{}{}\n'.format(lib, " "*(10-len(lib)),
getattr(ffmpeg, lib + '_version_string')))
else:
output.write('Blender was built without FFmpeg support\n')
if bpy.app.background: if bpy.app.background:
output.write('\nOpenGL: missing, background mode\n') output.write('\nOpenGL: missing, background mode\n')
else: else:

@ -11,4 +11,4 @@ else:
bpy.context.scene.render.ffmpeg_audio_mixrate = 48000 bpy.context.scene.render.ffmpeg_audio_mixrate = 48000
bpy.context.scene.render.ffmpeg_audio_codec = "PCM" bpy.context.scene.render.ffmpeg_audio_codec = "PCM"
bpy.context.scene.render.ffmpeg_audio_channels = 2 bpy.context.scene.render.ffmpeg_audio_channels = "STEREO"

@ -21,4 +21,4 @@ bpy.context.scene.render.ffmpeg_muxrate = 10080000
bpy.context.scene.render.ffmpeg_audio_codec = "AC3" bpy.context.scene.render.ffmpeg_audio_codec = "AC3"
bpy.context.scene.render.ffmpeg_audio_bitrate = 448 bpy.context.scene.render.ffmpeg_audio_bitrate = 448
bpy.context.scene.render.ffmpeg_audio_mixrate = 48000 bpy.context.scene.render.ffmpeg_audio_mixrate = 48000
bpy.context.scene.render.ffmpeg_audio_channels = 6 bpy.context.scene.render.ffmpeg_audio_channels = "SURROUND51"

@ -21,4 +21,4 @@ bpy.context.scene.render.ffmpeg_muxrate = 0
bpy.context.scene.render.ffmpeg_audio_bitrate = 224 bpy.context.scene.render.ffmpeg_audio_bitrate = 224
bpy.context.scene.render.ffmpeg_audio_mixrate = 44100 bpy.context.scene.render.ffmpeg_audio_mixrate = 44100
bpy.context.scene.render.ffmpeg_audio_codec = "MP2" bpy.context.scene.render.ffmpeg_audio_codec = "MP2"
bpy.context.scene.render.ffmpeg_audio_channels = 2 bpy.context.scene.render.ffmpeg_audio_channels = "STEREO"

@ -21,4 +21,4 @@ bpy.context.scene.render.ffmpeg_muxrate = 2352 * 75 * 8
bpy.context.scene.render.ffmpeg_audio_bitrate = 224 bpy.context.scene.render.ffmpeg_audio_bitrate = 224
bpy.context.scene.render.ffmpeg_audio_mixrate = 44100 bpy.context.scene.render.ffmpeg_audio_mixrate = 44100
bpy.context.scene.render.ffmpeg_audio_codec = "MP2" bpy.context.scene.render.ffmpeg_audio_codec = "MP2"
bpy.context.scene.render.ffmpeg_audio_channels = 2 bpy.context.scene.render.ffmpeg_audio_channels = "STEREO"

@ -0,0 +1,5 @@
import bpy
track = bpy.context.edit_movieclip.tracking.tracks.active
track.color = (1.0, 0.0, 1.0)
track.use_custom_color = True

@ -76,6 +76,7 @@ class AddPresetBase():
if hasattr(self, "add"): if hasattr(self, "add"):
self.add(context, filepath) self.add(context, filepath)
else: else:
print("Writing Preset: %r" % filepath)
file_preset = open(filepath, 'w') file_preset = open(filepath, 'w')
file_preset.write("import bpy\n") file_preset.write("import bpy\n")

@ -813,6 +813,20 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop(md, "width", slider=True) col.prop(md, "width", slider=True)
col.prop(md, "narrowness", slider=True) col.prop(md, "narrowness", slider=True)
def REMESH(self, layout, ob, md):
layout.prop(md, "mode")
layout.prop(md, "octree_depth")
layout.prop(md, "scale")
row = layout.row()
row.active = md.mode == "SHARP"
row.prop(md, "sharpness")
layout.prop(md, "remove_disconnected_pieces")
row = layout.row()
row.active = md.remove_disconnected_pieces
row.prop(md, "threshold")
@staticmethod @staticmethod
def vertex_weight_mask(layout, ob, md): def vertex_weight_mask(layout, ob, md):
layout.label(text="Influence/Mask Options:") layout.label(text="Influence/Mask Options:")

@ -560,10 +560,14 @@ class WORLD_PT_game_mist(WorldButtonsPanel, Panel):
world = context.world world = context.world
layout.active = world.mist_settings.use_mist layout.active = world.mist_settings.use_mist
row = layout.row() row = layout.row()
row.prop(world.mist_settings, "falloff")
row = layout.row(align=True)
row.prop(world.mist_settings, "start") row.prop(world.mist_settings, "start")
row.prop(world.mist_settings, "depth") row.prop(world.mist_settings, "depth")
row = layout.row()
row.prop(world.mist_settings, "intensity", text="Minimum Intensity")
class WORLD_PT_game_physics(WorldButtonsPanel, Panel): class WORLD_PT_game_physics(WorldButtonsPanel, Panel):

@ -755,7 +755,16 @@ class ConstraintButtonsPanel():
col = layout.column() col = layout.column()
col.prop(con, "rotation_range", text="Pivot When") col.prop(con, "rotation_range", text="Pivot When")
@staticmethod
def _getConstraintClip(context, con):
if not con.use_active_clip:
return con.clip
else:
return context.scene.active_clip
def FOLLOW_TRACK(self, context, layout, con): def FOLLOW_TRACK(self, context, layout, con):
clip = self._getConstraintClip(context, con)
row = layout.row() row = layout.row()
row.prop(con, "use_active_clip") row.prop(con, "use_active_clip")
row.prop(con, "use_3d_position") row.prop(con, "use_3d_position")
@ -763,7 +772,11 @@ class ConstraintButtonsPanel():
if not con.use_active_clip: if not con.use_active_clip:
layout.prop(con, "clip") layout.prop(con, "clip")
layout.prop(con, "track") if clip:
layout.prop_search(con, "object", clip.tracking, "objects", icon='OBJECT_DATA')
layout.prop_search(con, "track", clip.tracking, "tracks", icon='ANIMATION_DATA')
layout.prop(con, "camera")
layout.operator("clip.constraint_to_fcurve") layout.operator("clip.constraint_to_fcurve")
@ -775,6 +788,26 @@ class ConstraintButtonsPanel():
layout.operator("clip.constraint_to_fcurve") layout.operator("clip.constraint_to_fcurve")
def OBJECT_SOLVER(self, context, layout, con):
scene = context.scene
clip = self._getConstraintClip(context, con)
layout.prop(con, "use_active_clip")
if not con.use_active_clip:
layout.prop(con, "clip")
if clip:
layout.prop_search(con, "object", clip.tracking, "objects", icon='OBJECT_DATA')
layout.prop(con, "camera")
row = layout.row()
row.operator("constraint.objectsolver_set_inverse")
row.operator("constraint.objectsolver_clear_inverse")
layout.operator("clip.constraint_to_fcurve")
def SCRIPT(self, context, layout, con): def SCRIPT(self, context, layout, con):
layout.label("Blender 2.5 has no py-constraints") layout.label("Blender 2.5 has no py-constraints")

@ -835,6 +835,9 @@ class RENDER_PT_shading(RenderButtonsPanel, Panel):
col = split.column() col = split.column()
col.prop(rd, "use_raytrace", text="Ray Tracing") col.prop(rd, "use_raytrace", text="Ray Tracing")
col.prop(rd, "use_color_management") col.prop(rd, "use_color_management")
sub = col.row()
sub.active = rd.use_color_management == True
sub.prop(rd, "use_color_unpremultiply")
col.prop(rd, "alpha_mode", text="Alpha") col.prop(rd, "alpha_mode", text="Alpha")

@ -16,7 +16,8 @@
# #
# ##### END GPL LICENSE BLOCK ##### # ##### END GPL LICENSE BLOCK #####
# <pep8 compliant> # <pep8-80 compliant>
import bpy import bpy
from bpy.types import Panel, Header, Menu from bpy.types import Panel, Header, Menu
@ -70,7 +71,13 @@ class CLIP_HT_header(Header):
row.template_ID(sc, "clip", open='clip.open') row.template_ID(sc, "clip", open='clip.open')
if clip: if clip:
r = clip.tracking.reconstruction tracking = clip.tracking
active = tracking.objects.active
if active and not active.is_camera:
r = active.reconstruction
else:
r = tracking.reconstruction
if r.is_valid: if r.is_valid:
layout.label(text="Average solve error: %.4f" % layout.label(text="Average solve error: %.4f" %
@ -197,10 +204,15 @@ class CLIP_PT_tools_solve(Panel):
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
clip = context.space_data.clip clip = context.space_data.clip
settings = clip.tracking.settings tracking = clip.tracking
settings = tracking.settings
tracking_object = tracking.objects.active
col = layout.column(align=True) col = layout.column(align=True)
col.operator("clip.solve_camera", text="Camera Motion")
col.operator("clip.solve_camera",
text="Camera Motion" if tracking_object.is_camera
else "Object Motion")
col.operator("clip.clear_solution") col.operator("clip.clear_solution")
col = layout.column(align=True) col = layout.column(align=True)
@ -208,6 +220,7 @@ class CLIP_PT_tools_solve(Panel):
col.prop(settings, "keyframe_b") col.prop(settings, "keyframe_b")
col = layout.column(align=True) col = layout.column(align=True)
col.active = tracking_object.is_camera
col.label(text="Refine:") col.label(text="Refine:")
col.prop(settings, "refine_intrinsics", text="") col.prop(settings, "refine_intrinsics", text="")
@ -287,6 +300,39 @@ class CLIP_PT_tools_orientation(Panel):
col.prop(settings, "distance") col.prop(settings, "distance")
class CLIP_PT_tools_object(Panel):
bl_space_type = 'CLIP_EDITOR'
bl_region_type = 'TOOLS'
bl_label = "Object"
@classmethod
def poll(cls, context):
sc = context.space_data
clip = sc.clip
if clip and sc.mode == 'RECONSTRUCTION':
tracking_object = clip.tracking.objects.active
return not tracking_object.is_camera
return False
def draw(self, context):
sc = context.space_data
clip = sc.clip
layout = self.layout
tracking_object = clip.tracking.objects.active
settings = sc.clip.tracking.settings
col = layout.column()
col.prop(tracking_object, "scale")
col.separator()
col.operator("clip.set_solution_scale", text="Set Scale")
col.prop(settings, "object_distance")
class CLIP_PT_tools_grease_pencil(Panel): class CLIP_PT_tools_grease_pencil(Panel):
bl_space_type = 'CLIP_EDITOR' bl_space_type = 'CLIP_EDITOR'
bl_region_type = 'TOOLS' bl_region_type = 'TOOLS'
@ -316,6 +362,38 @@ class CLIP_PT_tools_grease_pencil(Panel):
row.prop(context.tool_settings, "use_grease_pencil_sessions") row.prop(context.tool_settings, "use_grease_pencil_sessions")
class CLIP_PT_objects(Panel):
bl_space_type = 'CLIP_EDITOR'
bl_region_type = 'UI'
bl_label = "Objects"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
sc = context.space_data
return sc.clip
def draw(self, context):
layout = self.layout
sc = context.space_data
clip = sc.clip
tracking = clip.tracking
row = layout.row()
row.template_list(tracking, "objects",
tracking, "active_object_index", rows=3)
sub = row.column(align=True)
sub.operator("clip.tracking_object_new", icon='ZOOMIN', text="")
sub.operator("clip.tracking_object_remove", icon='ZOOMOUT', text="")
active = tracking.objects.active
if active:
layout.prop(active, "name")
class CLIP_PT_track(Panel): class CLIP_PT_track(Panel):
bl_space_type = 'CLIP_EDITOR' bl_space_type = 'CLIP_EDITOR'
bl_region_type = 'UI' bl_region_type = 'UI'
@ -352,9 +430,15 @@ class CLIP_PT_track(Panel):
layout.template_track(sc, "scopes") layout.template_track(sc, "scopes")
row = layout.row(align=True) row = layout.row(align=True)
row.prop(act_track, "use_red_channel", text="R", toggle=True) sub = row.row()
row.prop(act_track, "use_green_channel", text="G", toggle=True) sub.prop(act_track, "use_red_channel", text="R", toggle=True)
row.prop(act_track, "use_blue_channel", text="B", toggle=True) sub.prop(act_track, "use_green_channel", text="G", toggle=True)
sub.prop(act_track, "use_blue_channel", text="B", toggle=True)
row.separator()
sub = row.row()
sub.prop(act_track, "use_grayscale_preview", text="B/W", toggle=True)
layout.separator() layout.separator()
@ -387,7 +471,7 @@ class CLIP_PT_tracking_camera(Panel):
def poll(cls, context): def poll(cls, context):
sc = context.space_data sc = context.space_data
return sc.mode in ['TRACKING', 'DISTORTION'] and sc.clip return sc.mode in {'TRACKING', 'DISTORTION'} and sc.clip
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
@ -422,7 +506,7 @@ class CLIP_PT_tracking_camera(Panel):
col.operator("clip.set_center_principal", text="Center") col.operator("clip.set_center_principal", text="Center")
col = layout.column(align=True) col = layout.column(align=True)
col.label(text="Undistortion:") col.label(text="Lens Distortion:")
col.prop(clip.tracking.camera, "k1") col.prop(clip.tracking.camera, "k1")
col.prop(clip.tracking.camera, "k2") col.prop(clip.tracking.camera, "k2")
col.prop(clip.tracking.camera, "k3") col.prop(clip.tracking.camera, "k3")

@ -34,28 +34,28 @@
*/ */
/* example of usage: /* example of usage:
*
int *arr = NULL; * int *arr = NULL;
V_DECLARE(arr); * V_DECLARE(arr);
int i; * int i;
*
for (i=0; i<10; i++) { * for (i=0; i<10; i++) {
V_GROW(arr); * V_GROW(arr);
arr[i] = something; * arr[i] = something;
} * }
V_FREE(arr); * V_FREE(arr);
*
arrays are buffered, using double-buffering (so on each reallocation, * arrays are buffered, using double-buffering (so on each reallocation,
the array size is doubled). supposedly this should give good Big Oh * the array size is doubled). supposedly this should give good Big Oh
behaviour, though it may not be the best in practice. * behaviour, though it may not be the best in practice.
*/ */
#define V_DECLARE(vec) int _##vec##_count=0; void *_##vec##_tmp #define V_DECLARE(vec) int _##vec##_count=0; void *_##vec##_tmp
/*in the future, I plan on having V_DECLARE allocate stack memory it'll /* in the future, I plan on having V_DECLARE allocate stack memory it'll
use at first, and switch over to heap when it needs more. that'll mess * use at first, and switch over to heap when it needs more. that'll mess
up cases where you'd want to use this API to build a dynamic list for * up cases where you'd want to use this API to build a dynamic list for
non-local use, so all such cases should use this macro.*/ * non-local use, so all such cases should use this macro.*/
#define V_DYNDECLARE(vec) V_DECLARE(vec) #define V_DYNDECLARE(vec) V_DECLARE(vec)
/*this returns the entire size of the array, including any buffering.*/ /*this returns the entire size of the array, including any buffering.*/

@ -45,9 +45,6 @@ struct rctf;
# define DO_INLINE static inline # define DO_INLINE static inline
#endif #endif
void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w);
void floatbuf_to_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w);
struct CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy); struct CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy);
void curvemapping_free(struct CurveMapping *cumap); void curvemapping_free(struct CurveMapping *cumap);
struct CurveMapping *curvemapping_copy(struct CurveMapping *cumap); struct CurveMapping *curvemapping_copy(struct CurveMapping *cumap);

@ -75,6 +75,9 @@ extern const CustomDataMask CD_MASK_FACECORNERS;
void CustomData_copy(const struct CustomData *source, struct CustomData *dest, void CustomData_copy(const struct CustomData *source, struct CustomData *dest,
CustomDataMask mask, int alloctype, int totelem); CustomDataMask mask, int alloctype, int totelem);
/* BMESH_TODO, not really a public function but readfile.c needs it */
void CustomData_update_typemap(struct CustomData *data);
/* same as the above, except that this will preserve existing layers, and only /* same as the above, except that this will preserve existing layers, and only
* add the layers that were not there yet */ * add the layers that were not there yet */
void CustomData_merge(const struct CustomData *source, struct CustomData *dest, void CustomData_merge(const struct CustomData *source, struct CustomData *dest,
@ -128,6 +131,7 @@ int CustomData_number_of_layers(const struct CustomData *data, int type);
void *CustomData_duplicate_referenced_layer(struct CustomData *data, const int type, const int totelem); void *CustomData_duplicate_referenced_layer(struct CustomData *data, const int type, const int totelem);
void *CustomData_duplicate_referenced_layer_named(struct CustomData *data, void *CustomData_duplicate_referenced_layer_named(struct CustomData *data,
const int type, const char *name, const int totelem); const int type, const char *name, const int totelem);
int CustomData_is_referenced_layer(struct CustomData *data, int type);
/* set the CD_FLAG_NOCOPY flag in custom data layers where the mask is /* set the CD_FLAG_NOCOPY flag in custom data layers where the mask is
* zero for the layer type, so only layer types specified by the mask * zero for the layer type, so only layer types specified by the mask
@ -144,12 +148,13 @@ void CustomData_set_only_copy(const struct CustomData *data,
void CustomData_copy_data(const struct CustomData *source, void CustomData_copy_data(const struct CustomData *source,
struct CustomData *dest, int source_index, struct CustomData *dest, int source_index,
int dest_index, int count); int dest_index, int count);
void CustomData_copy_elements(int type, void *source, void *dest, int count);
void CustomData_em_copy_data(const struct CustomData *source, void CustomData_em_copy_data(const struct CustomData *source,
struct CustomData *dest, void *src_block, struct CustomData *dest, void *src_block,
void **dest_block); void **dest_block);
void CustomData_bmesh_copy_data(const struct CustomData *source, void CustomData_bmesh_copy_data(const struct CustomData *source,
struct CustomData *dest,void *src_block, struct CustomData *dest, void *src_block,
void **dest_block); void **dest_block);
void CustomData_em_validate_data(struct CustomData *data, void *block, int sub_elements); void CustomData_em_validate_data(struct CustomData *data, void *block, int sub_elements);
/* frees data in a CustomData object /* frees data in a CustomData object
@ -191,11 +196,18 @@ void CustomData_swap(struct CustomData *data, int index, const int *corner_indic
* returns NULL if there is no layer of type * returns NULL if there is no layer of type
*/ */
void *CustomData_get(const struct CustomData *data, int index, int type); void *CustomData_get(const struct CustomData *data, int index, int type);
void *CustomData_get_n(const struct CustomData *data, int type, int index, int n);
void *CustomData_em_get(const struct CustomData *data, void *block, int type); void *CustomData_em_get(const struct CustomData *data, void *block, int type);
void *CustomData_em_get_n(const struct CustomData *data, void *block, int type, int n); void *CustomData_em_get_n(const struct CustomData *data, void *block, int type, int n);
void *CustomData_bmesh_get(const struct CustomData *data, void *block, int type); void *CustomData_bmesh_get(const struct CustomData *data, void *block, int type);
void *CustomData_bmesh_get_n(const struct CustomData *data, void *block, int type, int n); void *CustomData_bmesh_get_n(const struct CustomData *data, void *block, int type, int n);
/* gets the layer at physical index n, with no type checking.
*/
void *CustomData_bmesh_get_layer_n(const struct CustomData *data, void *block, int n);
int CustomData_set_layer_name(const struct CustomData *data, int type, int n, const char *name);
/* gets a pointer to the active or first layer of type /* gets a pointer to the active or first layer of type
* returns NULL if there is no layer of type * returns NULL if there is no layer of type
*/ */
@ -205,6 +217,7 @@ void *CustomData_get_layer_named(const struct CustomData *data, int type,
const char *name); const char *name);
int CustomData_get_layer_index(const struct CustomData *data, int type); int CustomData_get_layer_index(const struct CustomData *data, int type);
int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n);
int CustomData_get_named_layer_index(const struct CustomData *data, int type, const char *name); int CustomData_get_named_layer_index(const struct CustomData *data, int type, const char *name);
int CustomData_get_active_layer_index(const struct CustomData *data, int type); int CustomData_get_active_layer_index(const struct CustomData *data, int type);
int CustomData_get_render_layer_index(const struct CustomData *data, int type); int CustomData_get_render_layer_index(const struct CustomData *data, int type);
@ -231,6 +244,11 @@ void CustomData_bmesh_set(const struct CustomData *data, void *block, int type,
void CustomData_bmesh_set_n(struct CustomData *data, void *block, int type, int n, void CustomData_bmesh_set_n(struct CustomData *data, void *block, int type, int n,
void *source); void *source);
/*sets the data of the block at physical layer n. no real type checking
*is performed.
*/
void CustomData_bmesh_set_layer_n(struct CustomData *data, void *block, int n,
void *source);
/* set the pointer of to the first layer of type. the old data is not freed. /* set the pointer of to the first layer of type. the old data is not freed.
* returns the value of ptr if the layer is found, NULL otherwise * returns the value of ptr if the layer is found, NULL otherwise

@ -37,11 +37,13 @@ struct BoundBox;
struct DispList; struct DispList;
struct ListBase; struct ListBase;
struct EditMesh; struct EditMesh;
struct MDeformVert;
struct Mesh; struct Mesh;
struct MPoly;
struct MLoop;
struct MFace; struct MFace;
struct MEdge; struct MEdge;
struct MVert; struct MVert;
struct MDeformVert;
struct MCol; struct MCol;
struct Object; struct Object;
struct MTFace; struct MTFace;
@ -49,6 +51,7 @@ struct VecNor;
struct CustomData; struct CustomData;
struct DerivedMesh; struct DerivedMesh;
struct Scene; struct Scene;
struct MLoopUV;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -57,6 +60,11 @@ extern "C" {
struct EditMesh *BKE_mesh_get_editmesh(struct Mesh *me); struct EditMesh *BKE_mesh_get_editmesh(struct Mesh *me);
void BKE_mesh_end_editmesh(struct Mesh *me, struct EditMesh *em); void BKE_mesh_end_editmesh(struct Mesh *me, struct EditMesh *em);
/* for forwards compat only quad->tri polys to mface, skip ngons.
*/
int mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata,
struct CustomData *pdata, int totface, int totloop, int totpoly);
void unlink_mesh(struct Mesh *me); void unlink_mesh(struct Mesh *me);
void free_mesh(struct Mesh *me); void free_mesh(struct Mesh *me);
struct Mesh *add_mesh(const char *name); struct Mesh *add_mesh(const char *name);
@ -127,9 +135,9 @@ typedef struct IndexNode {
struct IndexNode *next, *prev; struct IndexNode *next, *prev;
int index; int index;
} IndexNode; } IndexNode;
void create_vert_face_map(ListBase **map, IndexNode **mem, const struct MFace *mface, void create_vert_face_map(struct ListBase **map, IndexNode **mem, const struct MFace *mface,
const int totvert, const int totface); const int totvert, const int totface);
void create_vert_edge_map(ListBase **map, IndexNode **mem, const struct MEdge *medge, void create_vert_edge_map(struct ListBase **map, IndexNode **mem, const struct MEdge *medge,
const int totvert, const int totedge); const int totvert, const int totedge);
/* functions for making menu's from customdata layers */ /* functions for making menu's from customdata layers */
@ -159,6 +167,12 @@ void BKE_mesh_calc_edges(struct Mesh *mesh, int update);
void BKE_mesh_ensure_navmesh(struct Mesh *me); void BKE_mesh_ensure_navmesh(struct Mesh *me);
/*convert a triangle of loop facedata to mface facedata*/
void mesh_loops_to_mface_corners(struct CustomData *fdata, struct CustomData *ldata,
struct CustomData *pdata, int lindex[4], int findex,
const int polyindex, const int mf_len,
const int numTex, const int numCol, const int hasWCol);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -34,11 +34,13 @@
struct bGPDlayer; struct bGPDlayer;
struct ImBuf; struct ImBuf;
struct ListBase;
struct MovieReconstructContext; struct MovieReconstructContext;
struct MovieTrackingTrack; struct MovieTrackingTrack;
struct MovieTrackingMarker; struct MovieTrackingMarker;
struct MovieTracking; struct MovieTracking;
struct MovieTrackingContext; struct MovieTrackingContext;
struct MovieTrackingObject;
struct MovieClipUser; struct MovieClipUser;
struct MovieDistortion; struct MovieDistortion;
struct Camera; struct Camera;
@ -49,8 +51,8 @@ void BKE_tracking_init_settings(struct MovieTracking *tracking);
void BKE_tracking_clamp_track(struct MovieTrackingTrack *track, int event); void BKE_tracking_clamp_track(struct MovieTrackingTrack *track, int event);
void BKE_tracking_track_flag(struct MovieTrackingTrack *track, int area, int flag, int clear); void BKE_tracking_track_flag(struct MovieTrackingTrack *track, int area, int flag, int clear);
struct MovieTrackingTrack *BKE_tracking_add_track(struct MovieTracking *tracking, float x, float y, struct MovieTrackingTrack *BKE_tracking_add_track(struct MovieTracking *tracking, struct ListBase *tracksbase,
int framenr, int width, int height); float x, float y, int framenr, int width, int height);
void BKE_tracking_insert_marker(struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker); void BKE_tracking_insert_marker(struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker);
void BKE_tracking_delete_marker(struct MovieTrackingTrack *track, int framenr); void BKE_tracking_delete_marker(struct MovieTrackingTrack *track, int framenr);
@ -72,40 +74,54 @@ struct ImBuf *BKE_tracking_get_pattern_imbuf(struct ImBuf *ibuf, struct MovieTra
struct ImBuf *BKE_tracking_get_search_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track, struct ImBuf *BKE_tracking_get_search_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track,
struct MovieTrackingMarker *marker, int margin, int anchored, float pos[2], int origin[2]); struct MovieTrackingMarker *marker, int margin, int anchored, float pos[2], int origin[2]);
void BKE_track_unique_name(struct MovieTracking *tracking, struct MovieTrackingTrack *track); void BKE_track_unique_name(struct ListBase *tracksbase, struct MovieTrackingTrack *track);
struct MovieTrackingTrack *BKE_tracking_named_track(struct MovieTracking *tracking, const char *name); struct MovieTrackingTrack *BKE_tracking_named_track(struct MovieTracking *tracking, struct MovieTrackingObject *object, const char *name);
struct MovieTrackingTrack *BKE_tracking_indexed_track(struct MovieTracking *tracking, int tracknr); struct MovieTrackingTrack *BKE_tracking_indexed_track(struct MovieTracking *tracking, int tracknr, struct ListBase **tracksbase_r);
void BKE_tracking_camera_shift(struct MovieTracking *tracking, int winx, int winy, float *shiftx, float *shifty); void BKE_tracking_camera_shift(struct MovieTracking *tracking, int winx, int winy, float *shiftx, float *shifty);
void BKE_tracking_camera_to_blender(struct MovieTracking *tracking, struct Scene *scene, struct Camera *camera, int width, int height); void BKE_tracking_camera_to_blender(struct MovieTracking *tracking, struct Scene *scene, struct Camera *camera, int width, int height);
void BKE_get_tracking_mat(struct Scene *scene, struct Object *ob, float mat[4][4]); void BKE_get_tracking_mat(struct Scene *scene, struct Object *ob, float mat[4][4]);
void BKE_tracking_projection_matrix(struct MovieTracking *tracking, int framenr, int winx, int winy, float mat[4][4]); void BKE_tracking_projection_matrix(struct MovieTracking *tracking, struct MovieTrackingObject *object,
int framenr, int winx, int winy, float mat[4][4]);
struct ListBase *BKE_tracking_get_tracks(struct MovieTracking *tracking);
struct MovieTrackingReconstruction *BKE_tracking_get_reconstruction(struct MovieTracking *tracking);
struct MovieTrackingTrack *BKE_tracking_active_track(struct MovieTracking *tracking);
struct MovieTrackingObject *BKE_tracking_active_object(struct MovieTracking *tracking);
struct MovieTrackingObject *BKE_tracking_get_camera_object(struct MovieTracking *tracking);
struct ListBase *BKE_tracking_object_tracks(struct MovieTracking *tracking, struct MovieTrackingObject *object);
struct MovieTrackingReconstruction *BKE_tracking_object_reconstruction(struct MovieTracking *tracking,
struct MovieTrackingObject *object);
/* 2D tracking */ /* 2D tracking */
struct MovieTrackingContext *BKE_tracking_context_new(struct MovieClip *clip, struct MovieClipUser *user, struct MovieTrackingContext *BKE_tracking_context_new(struct MovieClip *clip, struct MovieClipUser *user,
short backwards, short disable_failed, short sequence); short backwards, short sequence);
void BKE_tracking_context_free(struct MovieTrackingContext *context); void BKE_tracking_context_free(struct MovieTrackingContext *context);
void BKE_tracking_sync(struct MovieTrackingContext *context); void BKE_tracking_sync(struct MovieTrackingContext *context);
void BKE_tracking_sync_user(struct MovieClipUser *user, struct MovieTrackingContext *context); void BKE_tracking_sync_user(struct MovieClipUser *user, struct MovieTrackingContext *context);
int BKE_tracking_next(struct MovieTrackingContext *context); int BKE_tracking_next(struct MovieTrackingContext *context);
/* Camera solving */ /* Camera solving */
int BKE_tracking_can_reconstruct(struct MovieTracking *tracking, char *error_msg, int error_size); int BKE_tracking_can_reconstruct(struct MovieTracking *tracking, struct MovieTrackingObject *object,
char *error_msg, int error_size);
struct MovieReconstructContext* BKE_tracking_reconstruction_context_new(struct MovieTracking *tracking, struct MovieReconstructContext* BKE_tracking_reconstruction_context_new(struct MovieTracking *tracking,
int keyframe1, int keyframe2, int width, int height); struct MovieTrackingObject *object, int keyframe1, int keyframe2, int width, int height);
void BKE_tracking_reconstruction_context_free(struct MovieReconstructContext *context); void BKE_tracking_reconstruction_context_free(struct MovieReconstructContext *context);
void BKE_tracking_solve_reconstruction(struct MovieReconstructContext *context, void BKE_tracking_solve_reconstruction(struct MovieReconstructContext *context,
short *stop, short *do_update, float *progress, char *stats_message, int message_size); short *stop, short *do_update, float *progress, char *stats_message, int message_size);
int BKE_tracking_finish_reconstruction(struct MovieReconstructContext *context, struct MovieTracking *tracking); int BKE_tracking_finish_reconstruction(struct MovieReconstructContext *context, struct MovieTracking *tracking);
struct MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(struct MovieTracking *tracking, int framenr); struct MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(struct MovieTracking *tracking,
void BKE_tracking_get_interpolated_camera(struct MovieTracking *tracking, int framenr, float mat[4][4]); struct MovieTrackingObject *object, int framenr);
void BKE_tracking_get_interpolated_camera(struct MovieTracking *tracking,
struct MovieTrackingObject *object, int framenr, float mat[4][4]);
/* Feature detection */ /* Feature detection */
void BKE_tracking_detect_fast(struct MovieTracking *tracking, struct ImBuf *imbuf, void BKE_tracking_detect_fast(struct MovieTracking *tracking, struct ListBase *tracksbase, struct ImBuf *imbuf,
int framenr, int margin, int min_trackness, int min_distance, struct bGPDlayer *layer, int framenr, int margin, int min_trackness, int min_distance, struct bGPDlayer *layer,
int place_outside_layer); int place_outside_layer);
@ -127,8 +143,14 @@ void BKE_tracking_distortion_destroy(struct MovieDistortion *distortion);
struct ImBuf *BKE_tracking_undistort(struct MovieTracking *tracking, struct ImBuf *ibuf, int width, int height, float overscan); struct ImBuf *BKE_tracking_undistort(struct MovieTracking *tracking, struct ImBuf *ibuf, int width, int height, float overscan);
struct ImBuf *BKE_tracking_distort(struct MovieTracking *tracking, struct ImBuf *ibuf, int width, int height, float overscan); struct ImBuf *BKE_tracking_distort(struct MovieTracking *tracking, struct ImBuf *ibuf, int width, int height, float overscan);
/* Object tracking */
struct MovieTrackingObject *BKE_tracking_new_object(struct MovieTracking *tracking, const char *name);
void BKE_tracking_remove_object(struct MovieTracking *tracking, struct MovieTrackingObject *object);
void BKE_tracking_object_unique_name(struct MovieTracking *tracking, struct MovieTrackingObject *object);
struct MovieTrackingObject *BKE_tracking_named_object(struct MovieTracking *tracking, const char *name);
/* Select */ /* Select */
void BKE_tracking_select_track(struct MovieTracking *tracking, struct MovieTrackingTrack *track, int area, int extend); void BKE_tracking_select_track(struct ListBase *tracksbase, struct MovieTrackingTrack *track, int area, int extend);
void BKE_tracking_deselect_track(struct MovieTrackingTrack *track, int area); void BKE_tracking_deselect_track(struct MovieTrackingTrack *track, int area);
#define TRACK_SELECTED(track) ((((track)->flag&TRACK_HIDDEN)==0) && ((track)->flag&SELECT || (track)->pat_flag&SELECT || (track)->search_flag&SELECT)) #define TRACK_SELECTED(track) ((((track)->flag&TRACK_HIDDEN)==0) && ((track)->flag&SELECT || (track)->pat_flag&SELECT || (track)->search_flag&SELECT))

@ -1216,6 +1216,9 @@ struct ImBuf *brush_gen_radial_control_imbuf(Brush *br)
/* Unified Size and Strength */ /* Unified Size and Strength */
/* XXX, wouldnt it be better to only pass the active scene?
* this can return any old scene! - campbell*/
static void set_unified_settings(Brush *brush, short flag, int value) static void set_unified_settings(Brush *brush, short flag, int value)
{ {
Scene *sce; Scene *sce;
@ -1369,7 +1372,9 @@ static float unified_unprojected_radius(Brush *brush)
} }
void brush_set_size(Brush *brush, int size) void brush_set_size(Brush *brush, int size)
{ {
if (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) const short us_flag = unified_settings(brush);
if (us_flag & SCULPT_PAINT_USE_UNIFIED_SIZE)
set_unified_size(brush, size); set_unified_size(brush, size);
else else
brush->size= size; brush->size= size;
@ -1379,12 +1384,16 @@ void brush_set_size(Brush *brush, int size)
int brush_size(Brush *brush) int brush_size(Brush *brush)
{ {
return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) ? unified_size(brush) : brush->size; const short us_flag = unified_settings(brush);
return (us_flag & SCULPT_PAINT_USE_UNIFIED_SIZE) ? unified_size(brush) : brush->size;
} }
void brush_set_use_locked_size(Brush *brush, int value) void brush_set_use_locked_size(Brush *brush, int value)
{ {
if (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) { const short us_flag = unified_settings(brush);
if (us_flag & SCULPT_PAINT_USE_UNIFIED_SIZE) {
set_unified_settings(brush, SCULPT_PAINT_UNIFIED_LOCK_BRUSH_SIZE, value); set_unified_settings(brush, SCULPT_PAINT_UNIFIED_LOCK_BRUSH_SIZE, value);
} }
else { else {
@ -1399,12 +1408,18 @@ void brush_set_use_locked_size(Brush *brush, int value)
int brush_use_locked_size(Brush *brush) int brush_use_locked_size(Brush *brush)
{ {
return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) ? (unified_settings(brush) & SCULPT_PAINT_UNIFIED_LOCK_BRUSH_SIZE) : (brush->flag & BRUSH_LOCK_SIZE); const short us_flag = unified_settings(brush);
return (us_flag & SCULPT_PAINT_USE_UNIFIED_SIZE) ?
(us_flag & SCULPT_PAINT_UNIFIED_LOCK_BRUSH_SIZE) :
(brush->flag & BRUSH_LOCK_SIZE);
} }
void brush_set_use_size_pressure(Brush *brush, int value) void brush_set_use_size_pressure(Brush *brush, int value)
{ {
if (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) { const short us_flag = unified_settings(brush);
if (us_flag & SCULPT_PAINT_USE_UNIFIED_SIZE) {
set_unified_settings(brush, SCULPT_PAINT_UNIFIED_SIZE_PRESSURE, value); set_unified_settings(brush, SCULPT_PAINT_UNIFIED_SIZE_PRESSURE, value);
} }
else { else {
@ -1419,12 +1434,18 @@ void brush_set_use_size_pressure(Brush *brush, int value)
int brush_use_size_pressure(Brush *brush) int brush_use_size_pressure(Brush *brush)
{ {
return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) ? (unified_settings(brush) & SCULPT_PAINT_UNIFIED_SIZE_PRESSURE) : (brush->flag & BRUSH_SIZE_PRESSURE); const short us_flag = unified_settings(brush);
return (us_flag & SCULPT_PAINT_USE_UNIFIED_SIZE) ?
(us_flag & SCULPT_PAINT_UNIFIED_SIZE_PRESSURE) :
(brush->flag & BRUSH_SIZE_PRESSURE);
} }
void brush_set_use_alpha_pressure(Brush *brush, int value) void brush_set_use_alpha_pressure(Brush *brush, int value)
{ {
if (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_ALPHA) { const short us_flag = unified_settings(brush);
if (us_flag & SCULPT_PAINT_USE_UNIFIED_ALPHA) {
set_unified_settings(brush, SCULPT_PAINT_UNIFIED_ALPHA_PRESSURE, value); set_unified_settings(brush, SCULPT_PAINT_UNIFIED_ALPHA_PRESSURE, value);
} }
else { else {
@ -1439,12 +1460,18 @@ void brush_set_use_alpha_pressure(Brush *brush, int value)
int brush_use_alpha_pressure(Brush *brush) int brush_use_alpha_pressure(Brush *brush)
{ {
return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_ALPHA) ? (unified_settings(brush) & SCULPT_PAINT_UNIFIED_ALPHA_PRESSURE) : (brush->flag & BRUSH_ALPHA_PRESSURE); const short us_flag = unified_settings(brush);
return (us_flag & SCULPT_PAINT_USE_UNIFIED_ALPHA) ?
(us_flag & SCULPT_PAINT_UNIFIED_ALPHA_PRESSURE) :
(brush->flag & BRUSH_ALPHA_PRESSURE);
} }
void brush_set_unprojected_radius(Brush *brush, float unprojected_radius) void brush_set_unprojected_radius(Brush *brush, float unprojected_radius)
{ {
if (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) const short us_flag = unified_settings(brush);
if (us_flag & SCULPT_PAINT_USE_UNIFIED_SIZE)
set_unified_unprojected_radius(brush, unprojected_radius); set_unified_unprojected_radius(brush, unprojected_radius);
else else
brush->unprojected_radius= unprojected_radius; brush->unprojected_radius= unprojected_radius;
@ -1454,12 +1481,18 @@ void brush_set_unprojected_radius(Brush *brush, float unprojected_radius)
float brush_unprojected_radius(Brush *brush) float brush_unprojected_radius(Brush *brush)
{ {
return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) ? unified_unprojected_radius(brush) : brush->unprojected_radius; const short us_flag = unified_settings(brush);
return (us_flag & SCULPT_PAINT_USE_UNIFIED_SIZE) ?
unified_unprojected_radius(brush) :
brush->unprojected_radius;
} }
void brush_set_alpha(Brush *brush, float alpha) void brush_set_alpha(Brush *brush, float alpha)
{ {
if (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_ALPHA) const short us_flag = unified_settings(brush);
if (us_flag & SCULPT_PAINT_USE_UNIFIED_ALPHA)
set_unified_alpha(brush, alpha); set_unified_alpha(brush, alpha);
else else
brush->alpha= alpha; brush->alpha= alpha;
@ -1469,5 +1502,9 @@ void brush_set_alpha(Brush *brush, float alpha)
float brush_alpha(Brush *brush) float brush_alpha(Brush *brush)
{ {
return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_ALPHA) ? unified_alpha(brush) : brush->alpha; const short us_flag = unified_settings(brush);
return (us_flag & SCULPT_PAINT_USE_UNIFIED_ALPHA) ?
unified_alpha(brush) :
brush->alpha;
} }

@ -1951,7 +1951,7 @@ void CDDM_calc_edges(DerivedMesh *dm)
index = CustomData_get_layer(&edgeData, CD_ORIGINDEX); index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
for(i = 0; !BLI_edgehashIterator_isDone(ehi); for(i = 0; !BLI_edgehashIterator_isDone(ehi);
BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) { BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2); BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2);
med->flag = ME_EDGEDRAW|ME_EDGERENDER; med->flag = ME_EDGEDRAW|ME_EDGERENDER;
*index = ORIGINDEX_NONE; *index = ORIGINDEX_NONE;

@ -52,45 +52,6 @@
#include "IMB_imbuf.h" #include "IMB_imbuf.h"
#include "IMB_imbuf_types.h" #include "IMB_imbuf_types.h"
void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int UNUSED(w))
{
int x, y;
float *rf= rectf;
float srgb[3];
unsigned char *rc= rectc;
for(y=y1; y<y2; y++) {
for(x=x1; x<x2; x++, rf+=4, rc+=4) {
srgb[0]= linearrgb_to_srgb(rf[0]);
srgb[1]= linearrgb_to_srgb(rf[1]);
srgb[2]= linearrgb_to_srgb(rf[2]);
rc[0]= FTOCHAR(srgb[0]);
rc[1]= FTOCHAR(srgb[1]);
rc[2]= FTOCHAR(srgb[2]);
rc[3]= FTOCHAR(rf[3]);
}
}
}
void floatbuf_to_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int UNUSED(w))
{
int x, y;
float *rf= rectf;
unsigned char *rc= rectc;
for(y=y1; y<y2; y++) {
for(x=x1; x<x2; x++, rf+=4, rc+=4) {
rc[0]= FTOCHAR(rf[0]);
rc[1]= FTOCHAR(rf[1]);
rc[2]= FTOCHAR(rf[2]);
rc[3]= FTOCHAR(rf[3]);
}
}
}
/* ********************************* color curve ********************* */ /* ********************************* color curve ********************* */
/* ***************** operations on full struct ************* */ /* ***************** operations on full struct ************* */

@ -1255,6 +1255,7 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr
float quat[4]; float quat[4];
if ((data->followflag & FOLLOWPATH_STATIC) == 0) { if ((data->followflag & FOLLOWPATH_STATIC) == 0) {
/* animated position along curve depending on time */ /* animated position along curve depending on time */
Nurb *nu = cu->nurb.first;
curvetime= cu->ctime - data->offset; curvetime= cu->ctime - data->offset;
/* ctime is now a proper var setting of Curve which gets set by Animato like any other var that's animated, /* ctime is now a proper var setting of Curve which gets set by Animato like any other var that's animated,
@ -1264,7 +1265,18 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr
* factor, which then gets clamped to lie within 0.0 - 1.0 range * factor, which then gets clamped to lie within 0.0 - 1.0 range
*/ */
curvetime /= cu->pathlen; curvetime /= cu->pathlen;
CLAMP(curvetime, 0.0f, 1.0f);
if (nu && nu->flagu & CU_NURB_CYCLIC) {
/* If the curve is cyclic, enable looping around if the time is
* outside the bounds 0..1 */
if ((curvetime < 0.0f) || (curvetime > 1.0f)) {
curvetime -= floor(curvetime);
}
}
else {
/* The curve is not cyclic, so clamp to the begin/end points. */
CLAMP(curvetime, 0.0f, 1.0f);
}
} }
else { else {
/* fixed position along curve */ /* fixed position along curve */
@ -3937,6 +3949,7 @@ static void followtrack_id_looper (bConstraint *con, ConstraintIDFunc func, void
bFollowTrackConstraint *data= con->data; bFollowTrackConstraint *data= con->data;
func(con, (ID**)&data->clip, userdata); func(con, (ID**)&data->clip, userdata);
func(con, (ID**)&data->camera, userdata);
} }
static void followtrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) static void followtrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets))
@ -3944,105 +3957,126 @@ static void followtrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase
Scene *scene= cob->scene; Scene *scene= cob->scene;
bFollowTrackConstraint *data= con->data; bFollowTrackConstraint *data= con->data;
MovieClip *clip= data->clip; MovieClip *clip= data->clip;
MovieTracking *tracking;
MovieTrackingTrack *track; MovieTrackingTrack *track;
MovieTrackingObject *tracking_object;
Object *camob= data->camera ? data->camera : scene->camera;
if (data->flag & FOLLOWTRACK_ACTIVECLIP) if (data->flag & FOLLOWTRACK_ACTIVECLIP)
clip= scene->clip; clip= scene->clip;
if (!clip || !data->track[0]) if (!clip || !data->track[0] || !camob)
return; return;
track= BKE_tracking_named_track(&clip->tracking, data->track); tracking= &clip->tracking;
if(data->object[0])
tracking_object= BKE_tracking_named_object(tracking, data->object);
else
tracking_object= BKE_tracking_get_camera_object(tracking);
if(!tracking_object)
return;
track= BKE_tracking_named_track(tracking, tracking_object, data->track);
if (!track) if (!track)
return; return;
if (data->flag & FOLLOWTRACK_USE_3D_POSITION) { if (data->flag & FOLLOWTRACK_USE_3D_POSITION) {
if (track->flag & TRACK_HAS_BUNDLE) { if (track->flag & TRACK_HAS_BUNDLE) {
float pos[3], mat[4][4], obmat[4][4]; MovieTracking *tracking= &clip->tracking;
float obmat[4][4], mat[4][4];
copy_m4_m4(obmat, cob->matrix); copy_m4_m4(obmat, cob->matrix);
BKE_get_tracking_mat(cob->scene, NULL, mat); if((tracking_object->flag&TRACKING_OBJECT_CAMERA)==0) {
mul_v3_m4v3(pos, mat, track->bundle_pos); float imat[4][4];
cob->matrix[3][0] += pos[0]; copy_m4_m4(mat, camob->obmat);
cob->matrix[3][1] += pos[1];
cob->matrix[3][2] += pos[2]; BKE_tracking_get_interpolated_camera(tracking, tracking_object, scene->r.cfra, imat);
invert_m4(imat);
mul_serie_m4(cob->matrix, obmat, mat, imat, NULL, NULL, NULL, NULL, NULL);
translate_m4(cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
}
else {
BKE_get_tracking_mat(cob->scene, camob, mat);
mult_m4_m4m4(cob->matrix, obmat, mat);
translate_m4(cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
}
} }
} }
else { else {
Object *camob= cob->scene->camera; MovieClipUser user;
MovieTrackingMarker *marker;
float vec[3], disp[3], axis[3], mat[4][4];
float aspect= (scene->r.xsch*scene->r.xasp) / (scene->r.ysch*scene->r.yasp);
float len, d;
if (camob) { where_is_object_mat(scene, camob, mat);
MovieClipUser user;
MovieTrackingMarker *marker;
float vec[3], disp[3], axis[3], mat[4][4];
float aspect= (scene->r.xsch*scene->r.xasp) / (scene->r.ysch*scene->r.yasp);
float len, d;
where_is_object_mat(scene, camob, mat); /* camera axis */
vec[0]= 0.0f;
vec[1]= 0.0f;
vec[2]= 1.0f;
mul_v3_m4v3(axis, mat, vec);
/* camera axis */ /* distance to projection plane */
vec[0]= 0.0f; copy_v3_v3(vec, cob->matrix[3]);
vec[1]= 0.0f; sub_v3_v3(vec, mat[3]);
vec[2]= 1.0f; project_v3_v3v3(disp, vec, axis);
mul_v3_m4v3(axis, mat, vec);
/* distance to projection plane */ len= len_v3(disp);
copy_v3_v3(vec, cob->matrix[3]);
sub_v3_v3(vec, mat[3]);
project_v3_v3v3(disp, vec, axis);
len= len_v3(disp); if (len > FLT_EPSILON) {
CameraParams params;
float pos[2], rmat[4][4];
if (len > FLT_EPSILON) { user.framenr= scene->r.cfra;
CameraParams params; marker= BKE_tracking_get_marker(track, user.framenr);
float pos[2], rmat[4][4];
user.framenr= scene->r.cfra; add_v2_v2v2(pos, marker->pos, track->offset);
marker= BKE_tracking_get_marker(track, user.framenr);
add_v2_v2v2(pos, marker->pos, track->offset); camera_params_init(&params);
camera_params_from_object(&params, camob);
camera_params_init(&params); if (params.is_ortho) {
camera_params_from_object(&params, camob); vec[0]= params.ortho_scale * (pos[0]-0.5f+params.shiftx);
vec[1]= params.ortho_scale * (pos[1]-0.5f+params.shifty);
vec[2]= -len;
if (params.is_ortho) { if (aspect > 1.0f) vec[1] /= aspect;
vec[0]= params.ortho_scale * (pos[0]-0.5f+params.shiftx); else vec[0] *= aspect;
vec[1]= params.ortho_scale * (pos[1]-0.5f+params.shifty);
vec[2]= -len;
if (aspect > 1.0f) vec[1] /= aspect; mul_v3_m4v3(disp, camob->obmat, vec);
else vec[0] *= aspect;
mul_v3_m4v3(disp, camob->obmat, vec); copy_m4_m4(rmat, camob->obmat);
zero_v3(rmat[3]);
mult_m4_m4m4(cob->matrix, cob->matrix, rmat);
copy_m4_m4(rmat, camob->obmat); copy_v3_v3(cob->matrix[3], disp);
zero_v3(rmat[3]); }
mult_m4_m4m4(cob->matrix, cob->matrix, rmat); else {
d= (len*params.sensor_x) / (2.0f*params.lens);
copy_v3_v3(cob->matrix[3], disp); vec[0]= d*(2.0f*(pos[0]+params.shiftx)-1.0f);
} vec[1]= d*(2.0f*(pos[1]+params.shifty)-1.0f);
else { vec[2]= -len;
d= (len*params.sensor_x) / (2.0f*params.lens);
vec[0]= d*(2.0f*(pos[0]+params.shiftx)-1.0f); if (aspect > 1.0f) vec[1] /= aspect;
vec[1]= d*(2.0f*(pos[1]+params.shifty)-1.0f); else vec[0] *= aspect;
vec[2]= -len;
if (aspect > 1.0f) vec[1] /= aspect; mul_v3_m4v3(disp, camob->obmat, vec);
else vec[0] *= aspect;
mul_v3_m4v3(disp, camob->obmat, vec); /* apply camera rotation so Z-axis would be co-linear */
copy_m4_m4(rmat, camob->obmat);
zero_v3(rmat[3]);
mult_m4_m4m4(cob->matrix, cob->matrix, rmat);
/* apply camera rotation so Z-axis would be co-linear */ copy_v3_v3(cob->matrix[3], disp);
copy_m4_m4(rmat, camob->obmat);
zero_v3(rmat[3]);
mult_m4_m4m4(cob->matrix, cob->matrix, rmat);
copy_v3_v3(cob->matrix[3], disp);
}
} }
} }
} }
@ -4092,10 +4126,13 @@ static void camerasolver_evaluate (bConstraint *con, bConstraintOb *cob, ListBas
if (clip) { if (clip) {
float mat[4][4], obmat[4][4]; float mat[4][4], obmat[4][4];
MovieTracking *tracking= &clip->tracking;
MovieTrackingObject *object= BKE_tracking_get_camera_object(tracking);
BKE_tracking_get_interpolated_camera(&clip->tracking, scene->r.cfra, mat); BKE_tracking_get_interpolated_camera(tracking, object, scene->r.cfra, mat);
copy_m4_m4(obmat, cob->matrix); copy_m4_m4(obmat, cob->matrix);
mult_m4_m4m4(cob->matrix, obmat, mat); mult_m4_m4m4(cob->matrix, obmat, mat);
} }
} }
@ -4116,6 +4153,80 @@ static bConstraintTypeInfo CTI_CAMERASOLVER = {
camerasolver_evaluate /* evaluate */ camerasolver_evaluate /* evaluate */
}; };
/* ----------- Object Solver ------------- */
static void objectsolver_new_data (void *cdata)
{
bObjectSolverConstraint *data= (bObjectSolverConstraint *)cdata;
data->clip = NULL;
data->flag |= OBJECTSOLVER_ACTIVECLIP;
unit_m4(data->invmat);
}
static void objectsolver_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata)
{
bObjectSolverConstraint *data= con->data;
func(con, (ID**)&data->clip, userdata);
func(con, (ID**)&data->camera, userdata);
}
static void objectsolver_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets))
{
Scene *scene= cob->scene;
bObjectSolverConstraint *data= con->data;
MovieClip *clip= data->clip;
Object *camob= data->camera ? data->camera : scene->camera;
if (data->flag & OBJECTSOLVER_ACTIVECLIP)
clip= scene->clip;
if(!camob || !clip)
return;
if (clip) {
MovieTracking *tracking= &clip->tracking;
MovieTrackingObject *object;
object= BKE_tracking_named_object(tracking, data->object);
if(object) {
float mat[4][4], obmat[4][4], imat[4][4], cammat[4][4], camimat[4][4], parmat[4][4];
where_is_object_mat(scene, camob, cammat);
BKE_tracking_get_interpolated_camera(tracking, object, scene->r.cfra, mat);
invert_m4_m4(camimat, cammat);
mult_m4_m4m4(parmat, cammat, data->invmat);
copy_m4_m4(cammat, camob->obmat);
copy_m4_m4(obmat, cob->matrix);
invert_m4_m4(imat, mat);
mul_serie_m4(cob->matrix, cammat, imat, camimat, parmat, obmat, NULL, NULL, NULL);
}
}
}
static bConstraintTypeInfo CTI_OBJECTSOLVER = {
CONSTRAINT_TYPE_OBJECTSOLVER, /* type */
sizeof(bObjectSolverConstraint), /* size */
"Object Solver", /* name */
"bObjectSolverConstraint", /* struct name */
NULL, /* free data */
NULL, /* relink data */
objectsolver_id_looper, /* id looper */
NULL, /* copy data */
objectsolver_new_data, /* new data */
NULL, /* get constraint targets */
NULL, /* flush constraint targets */
NULL, /* get target matrix */
objectsolver_evaluate /* evaluate */
};
/* ************************* Constraints Type-Info *************************** */ /* ************************* Constraints Type-Info *************************** */
/* All of the constraints api functions use bConstraintTypeInfo structs to carry out /* All of the constraints api functions use bConstraintTypeInfo structs to carry out
* and operations that involve constraint specific code. * and operations that involve constraint specific code.
@ -4156,6 +4267,7 @@ static void constraints_init_typeinfo (void)
constraintsTypeInfo[25]= &CTI_PIVOT; /* Pivot Constraint */ constraintsTypeInfo[25]= &CTI_PIVOT; /* Pivot Constraint */
constraintsTypeInfo[26]= &CTI_FOLLOWTRACK; /* Follow Track Constraint */ constraintsTypeInfo[26]= &CTI_FOLLOWTRACK; /* Follow Track Constraint */
constraintsTypeInfo[27]= &CTI_CAMERASOLVER; /* Camera Solver Constraint */ constraintsTypeInfo[27]= &CTI_CAMERASOLVER; /* Camera Solver Constraint */
constraintsTypeInfo[28]= &CTI_OBJECTSOLVER; /* Object Solver Constraint */
} }
/* This function should be used for getting the appropriate type-info when only /* This function should be used for getting the appropriate type-info when only

@ -99,6 +99,14 @@ typedef struct LayerTypeInfo {
default is assumed to be all zeros */ default is assumed to be all zeros */
void (*set_default)(void *data, int count); void (*set_default)(void *data, int count);
/* functions necassary for geometry collapse*/
int (*equal)(void *data1, void *data2);
void (*multiply)(void *data, float fac);
void (*initminmax)(void *min, void *max);
void (*add)(void *data1, void *data2);
void (*dominmax)(void *data1, void *min, void *max);
void (*copyvalue)(void *source, void *dest);
/* a function to read data from a cdf file */ /* a function to read data from a cdf file */
int (*read)(CDataFile *cdf, void *data, int count); int (*read)(CDataFile *cdf, void *data, int count);
@ -226,13 +234,11 @@ static void layerInterp_msticky(void **sources, float *weights,
w = weights ? weights[i] : 1.0f; w = weights ? weights[i] : 1.0f;
mst = (MSticky*)sources[i]; mst = (MSticky*)sources[i];
co[0] += w*mst->co[0]; madd_v2_v2fl(co, mst->co, w);
co[1] += w*mst->co[1];
} }
mst = (MSticky*)dest; mst = (MSticky*)dest;
mst->co[0] = co[0]; copy_v2_v2(mst->co, co);
mst->co[1] = co[1];
} }
@ -251,13 +257,11 @@ static void layerInterp_tface(void **sources, float *weights,
{ {
MTFace *tf = dest; MTFace *tf = dest;
int i, j, k; int i, j, k;
float uv[4][2]; float uv[4][2] = {{0.0f}};
float *sub_weight; float *sub_weight;
if(count <= 0) return; if(count <= 0) return;
memset(uv, 0, sizeof(uv));
sub_weight = sub_weights; sub_weight = sub_weights;
for(i = 0; i < count; ++i) { for(i = 0; i < count; ++i) {
float weight = weights ? weights[i] : 1; float weight = weights ? weights[i] : 1;
@ -266,24 +270,17 @@ static void layerInterp_tface(void **sources, float *weights,
for(j = 0; j < 4; ++j) { for(j = 0; j < 4; ++j) {
if(sub_weights) { if(sub_weights) {
for(k = 0; k < 4; ++k, ++sub_weight) { for(k = 0; k < 4; ++k, ++sub_weight) {
float w = (*sub_weight) * weight; madd_v2_v2fl(uv[j], src->uv[k], (*sub_weight) * weight);
float *tmp_uv = src->uv[k];
uv[j][0] += tmp_uv[0] * w;
uv[j][1] += tmp_uv[1] * w;
} }
} else { }
uv[j][0] += src->uv[j][0] * weight; else {
uv[j][1] += src->uv[j][1] * weight; madd_v2_v2fl(uv[j], src->uv[j], weight);
} }
} }
} }
*tf = *(MTFace *)sources[0]; *tf = *(MTFace *)(*sources);
for(j = 0; j < 4; ++j) { memcpy(tf->uv, uv, sizeof(tf->uv));
tf->uv[j][0] = uv[j][0];
tf->uv[j][1] = uv[j][1];
}
} }
static void layerSwap_tface(void *data, const int *corner_indices) static void layerSwap_tface(void *data, const int *corner_indices)
@ -299,10 +296,9 @@ static void layerSwap_tface(void *data, const int *corner_indices)
int j; int j;
for(j = 0; j < 4; ++j) { for(j = 0; j < 4; ++j) {
int source_index = corner_indices[j]; const int source_index = corner_indices[j];
uv[j][0] = tf->uv[source_index][0]; copy_v2_v2(uv[j], tf->uv[source_index]);
uv[j][1] = tf->uv[source_index][1];
// swap pinning flags around // swap pinning flags around
if(tf->unwrap & pin_flags[source_index]) { if(tf->unwrap & pin_flags[source_index]) {
@ -331,6 +327,24 @@ static void layerDefault_tface(void *data, int count)
tf[i] = default_tf; tf[i] = default_tf;
} }
static void layerCopy_propFloat(const void *source, void *dest,
int count)
{
memcpy(dest, source, sizeof(MFloatProperty)*count);
}
static void layerCopy_propInt(const void *source, void *dest,
int count)
{
memcpy(dest, source, sizeof(MIntProperty)*count);
}
static void layerCopy_propString(const void *source, void *dest,
int count)
{
memcpy(dest, source, sizeof(MStringProperty)*count);
}
static void layerCopy_origspace_face(const void *source, void *dest, int count) static void layerCopy_origspace_face(const void *source, void *dest, int count)
{ {
const OrigSpaceFace *source_tf = (const OrigSpaceFace*)source; const OrigSpaceFace *source_tf = (const OrigSpaceFace*)source;
@ -346,13 +360,11 @@ static void layerInterp_origspace_face(void **sources, float *weights,
{ {
OrigSpaceFace *osf = dest; OrigSpaceFace *osf = dest;
int i, j, k; int i, j, k;
float uv[4][2]; float uv[4][2] = {{0.0f}};
float *sub_weight; float *sub_weight;
if(count <= 0) return; if(count <= 0) return;
memset(uv, 0, sizeof(uv));
sub_weight = sub_weights; sub_weight = sub_weights;
for(i = 0; i < count; ++i) { for(i = 0; i < count; ++i) {
float weight = weights ? weights[i] : 1; float weight = weights ? weights[i] : 1;
@ -361,24 +373,18 @@ static void layerInterp_origspace_face(void **sources, float *weights,
for(j = 0; j < 4; ++j) { for(j = 0; j < 4; ++j) {
if(sub_weights) { if(sub_weights) {
for(k = 0; k < 4; ++k, ++sub_weight) { for(k = 0; k < 4; ++k, ++sub_weight) {
float w = (*sub_weight) * weight; madd_v2_v2fl(uv[j], src->uv[k], (*sub_weight) * weight);
float *tmp_uv = src->uv[k];
uv[j][0] += tmp_uv[0] * w;
uv[j][1] += tmp_uv[1] * w;
} }
} else { } else {
uv[j][0] += src->uv[j][0] * weight; madd_v2_v2fl(uv[j], src->uv[j], weight);
uv[j][1] += src->uv[j][1] * weight;
} }
} }
} }
*osf = *(OrigSpaceFace *)sources[0]; #if 0 /* no need, this ONLY contains UV's */
for(j = 0; j < 4; ++j) { *osf = *(OrigSpaceFace *)(*sources);
osf->uv[j][0] = uv[j][0]; #endif
osf->uv[j][1] = uv[j][1]; memcpy(osf->uv, uv, sizeof(osf->uv));
}
} }
static void layerSwap_origspace_face(void *data, const int *corner_indices) static void layerSwap_origspace_face(void *data, const int *corner_indices)
@ -388,8 +394,7 @@ static void layerSwap_origspace_face(void *data, const int *corner_indices)
int j; int j;
for(j = 0; j < 4; ++j) { for(j = 0; j < 4; ++j) {
uv[j][0] = osf->uv[corner_indices[j]][0]; copy_v2_v2(uv[j], osf->uv[corner_indices[j]]);
uv[j][1] = osf->uv[corner_indices[j]][1];
} }
memcpy(osf->uv, uv, sizeof(osf->uv)); memcpy(osf->uv, uv, sizeof(osf->uv));
} }
@ -640,10 +645,83 @@ static size_t layerFilesize_mdisps(CDataFile *UNUSED(cdf), void *data, int count
} }
/* --------- */ /* --------- */
static void layerCopyValue_mloopcol(void *source, void *dest)
{
MLoopCol *m1 = source, *m2 = dest;
m2->r = m1->r;
m2->g = m1->g;
m2->b = m1->b;
m2->a = m1->a;
}
static int layerEqual_mloopcol(void *data1, void *data2)
{
MLoopCol *m1 = data1, *m2 = data2;
float r, g, b, a;
r = m1->r - m2->r;
g = m1->g - m2->g;
b = m1->b - m2->b;
a = m1->a - m2->a;
return r*r + g*g + b*b + a*a < 0.001;
}
static void layerMultiply_mloopcol(void *data, float fac)
{
MLoopCol *m = data;
m->r = (float)m->r * fac;
m->g = (float)m->g * fac;
m->b = (float)m->b * fac;
m->a = (float)m->a * fac;
}
static void layerAdd_mloopcol(void *data1, void *data2)
{
MLoopCol *m = data1, *m2 = data2;
m->r += m2->r;
m->g += m2->g;
m->b += m2->b;
m->a += m2->a;
}
static void layerDoMinMax_mloopcol(void *data, void *vmin, void *vmax)
{
MLoopCol *m = data;
MLoopCol *min = vmin, *max = vmax;
if (m->r < min->r) min->r = m->r;
if (m->g < min->g) min->g = m->g;
if (m->b < min->b) min->b = m->b;
if (m->a < min->a) min->a = m->a;
if (m->r > max->r) max->r = m->r;
if (m->g > max->g) max->g = m->g;
if (m->b > max->b) max->b = m->b;
if (m->a > max->a) max->a = m->a;
}
static void layerInitMinMax_mloopcol(void *vmin, void *vmax)
{
MLoopCol *min = vmin, *max = vmax;
min->r = 255;
min->g = 255;
min->b = 255;
min->a = 255;
max->r = 0;
max->g = 0;
max->b = 0;
max->a = 0;
}
static void layerDefault_mloopcol(void *data, int count) static void layerDefault_mloopcol(void *data, int count)
{ {
static MLoopCol default_mloopcol = {255,255,255,255}; MLoopCol default_mloopcol = {255,255,255,255};
MLoopCol *mlcol = (MLoopCol*)data; MLoopCol *mlcol = (MLoopCol*)data;
int i; int i;
for(i = 0; i < count; i++) for(i = 0; i < count; i++)
@ -695,33 +773,74 @@ static void layerInterp_mloopcol(void **sources, float *weights,
mc->g = (int)col.g; mc->g = (int)col.g;
mc->b = (int)col.b; mc->b = (int)col.b;
} }
static void layerCopyValue_mloopuv(void *source, void *dest)
{
MLoopUV *luv1 = source, *luv2 = dest;
copy_v2_v2(luv2->uv, luv1->uv);
}
static int layerEqual_mloopuv(void *data1, void *data2)
{
MLoopUV *luv1 = data1, *luv2 = data2;
return len_squared_v2v2(luv1->uv, luv2->uv) < 0.00001f;
}
static void layerMultiply_mloopuv(void *data, float fac)
{
MLoopUV *luv = data;
mul_v2_fl(luv->uv, fac);
}
static void layerInitMinMax_mloopuv(void *vmin, void *vmax)
{
MLoopUV *min = vmin, *max = vmax;
INIT_MINMAX2(min->uv, max->uv);
}
static void layerDoMinMax_mloopuv(void *data, void *vmin, void *vmax)
{
MLoopUV *min = vmin, *max = vmax, *luv = data;
DO_MINMAX2(luv->uv, min->uv, max->uv);
}
static void layerAdd_mloopuv(void *data1, void *data2)
{
MLoopUV *l1 = data1, *l2 = data2;
add_v2_v2(l1->uv, l2->uv);
}
static void layerInterp_mloopuv(void **sources, float *weights, static void layerInterp_mloopuv(void **sources, float *weights,
float *sub_weights, int count, void *dest) float *sub_weights, int count, void *dest)
{ {
MLoopUV *mluv = dest; MLoopUV *mluv = dest;
float *uv= mluv->uv;
int i; int i;
float *sub_weight;
struct {
float u;
float v;
}uv;
uv.u = uv.v = 0.0;
sub_weight = sub_weights; zero_v2(uv);
for(i = 0; i < count; ++i){
float weight = weights ? weights[i] : 1; if (sub_weights) {
MLoopUV *src = sources[i]; const float *sub_weight = sub_weights;
if(sub_weights){ for(i = 0; i < count; i++) {
uv.u += src->uv[0] * (*sub_weight) * weight; float weight = weights ? weights[i] : 1.0f;
uv.v += src->uv[1] * (*sub_weight) * weight; MLoopUV *src = sources[i];
madd_v2_v2fl(uv, src->uv, (*sub_weight) * weight);
sub_weight++; sub_weight++;
} else {
uv.u += src->uv[0] * weight;
uv.v += src->uv[1] * weight;
} }
} }
mluv->uv[0] = uv.u; else {
mluv->uv[1] = uv.v; for(i = 0; i < count; i++) {
float weight = weights ? weights[i] : 1;
MLoopUV *src = sources[i];
madd_v2_v2fl(uv, src->uv, weight);
}
}
} }
static void layerInterp_mcol(void **sources, float *weights, static void layerInterp_mcol(void **sources, float *weights,
@ -734,13 +853,12 @@ static void layerInterp_mcol(void **sources, float *weights,
float r; float r;
float g; float g;
float b; float b;
} col[4]; } col[4] = {{0.0f}};
float *sub_weight; float *sub_weight;
if(count <= 0) return; if(count <= 0) return;
memset(col, 0, sizeof(col));
sub_weight = sub_weights; sub_weight = sub_weights;
for(i = 0; i < count; ++i) { for(i = 0; i < count; ++i) {
float weight = weights ? weights[i] : 1; float weight = weights ? weights[i] : 1;
@ -749,10 +867,11 @@ static void layerInterp_mcol(void **sources, float *weights,
if(sub_weights) { if(sub_weights) {
MCol *src = sources[i]; MCol *src = sources[i];
for(k = 0; k < 4; ++k, ++sub_weight, ++src) { for(k = 0; k < 4; ++k, ++sub_weight, ++src) {
col[j].a += src->a * (*sub_weight) * weight; const float w= (*sub_weight) * weight;
col[j].r += src->r * (*sub_weight) * weight; col[j].a += src->a * w;
col[j].g += src->g * (*sub_weight) * weight; col[j].r += src->r * w;
col[j].b += src->b * (*sub_weight) * weight; col[j].g += src->g * w;
col[j].b += src->b * w;
} }
} else { } else {
MCol *src = sources[i]; MCol *src = sources[i];
@ -798,11 +917,56 @@ static void layerDefault_mcol(void *data, int count)
MCol *mcol = (MCol*)data; MCol *mcol = (MCol*)data;
int i; int i;
for(i = 0; i < 4*count; i++) for(i = 0; i < 4*count; i++) {
mcol[i] = default_mcol; mcol[i] = default_mcol;
}
} }
static void layerInterp_bweight(void **sources, float *weights,
float *UNUSED(sub_weights), int count, void *dest)
{
float *f = dest;
float **in = (float **)sources;
int i;
if(count <= 0) return;
*f = 0.0f;
if (weights) {
for(i = 0; i < count; ++i) {
*f += *in[i] * weights[i];
}
}
else {
for(i = 0; i < count; ++i) {
*f += *in[i];
}
}
}
static void layerInterp_shapekey(void **sources, float *weights,
float *UNUSED(sub_weights), int count, void *dest)
{
float *co = dest;
float **in = (float **)sources;
int i;
if(count <= 0) return;
zero_v3(co);
if (weights) {
for(i = 0; i < count; ++i) {
madd_v3_v3fl(co, in[i], weights[i]);
}
}
else {
for(i = 0; i < count; ++i) {
add_v3_v3(co, in[i]);
}
}
}
static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 0: CD_MVERT */ /* 0: CD_MVERT */
@ -829,14 +993,14 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 8: CD_NORMAL */ /* 8: CD_NORMAL */
/* 3 floats per normal vector */ /* 3 floats per normal vector */
{sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
/* 9: CD_FLAGS */ /* 9: CD_POLYINDEX */
{sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, {sizeof(int), "MIntProperty", 1, NULL, NULL, NULL, NULL, NULL, NULL},
/* 10: CD_PROP_FLT */ /* 10: CD_PROP_FLT */
{sizeof(MFloatProperty), "MFloatProperty",1,"Float",NULL,NULL,NULL,NULL}, {sizeof(MFloatProperty), "MFloatProperty",1,"Float", layerCopy_propFloat,NULL,NULL,NULL},
/* 11: CD_PROP_INT */ /* 11: CD_PROP_INT */
{sizeof(MIntProperty), "MIntProperty",1,"Int",NULL,NULL,NULL,NULL}, {sizeof(MIntProperty), "MIntProperty",1,"Int",layerCopy_propInt,NULL,NULL,NULL},
/* 12: CD_PROP_STR */ /* 12: CD_PROP_STR */
{sizeof(MStringProperty), "MStringProperty",1,"String",NULL,NULL,NULL,NULL}, {sizeof(MStringProperty), "MStringProperty",1,"String",layerCopy_propString,NULL,NULL,NULL},
/* 13: CD_ORIGSPACE */ /* 13: CD_ORIGSPACE */
{sizeof(OrigSpaceFace), "OrigSpaceFace", 1, "UVMap", layerCopy_origspace_face, NULL, {sizeof(OrigSpaceFace), "OrigSpaceFace", 1, "UVMap", layerCopy_origspace_face, NULL,
layerInterp_origspace_face, layerSwap_origspace_face, layerDefault_origspace_face}, layerInterp_origspace_face, layerSwap_origspace_face, layerDefault_origspace_face},
@ -845,15 +1009,20 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 15: CD_MTEXPOLY */ /* 15: CD_MTEXPOLY */
{sizeof(MTexPoly), "MTexPoly", 1, "Face Texture", NULL, NULL, NULL, NULL, NULL}, {sizeof(MTexPoly), "MTexPoly", 1, "Face Texture", NULL, NULL, NULL, NULL, NULL},
/* 16: CD_MLOOPUV */ /* 16: CD_MLOOPUV */
{sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL}, {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL,
layerEqual_mloopuv, layerMultiply_mloopuv, layerInitMinMax_mloopuv,
layerAdd_mloopuv, layerDoMinMax_mloopuv, layerCopyValue_mloopuv},
/* 17: CD_MLOOPCOL */ /* 17: CD_MLOOPCOL */
{sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol}, {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL,
layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol,
layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol},
/* 18: CD_TANGENT */ /* 18: CD_TANGENT */
{sizeof(float)*4*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, {sizeof(float)*4*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
/* 19: CD_MDISPS */ /* 19: CD_MDISPS */
{sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps, {sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps,
layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL, layerRead_mdisps, layerWrite_mdisps, layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL,
layerFilesize_mdisps, layerValidate_mdisps}, NULL, NULL, NULL, NULL, NULL, NULL,
layerRead_mdisps, layerWrite_mdisps, layerFilesize_mdisps, layerValidate_mdisps},
/* 20: CD_WEIGHT_MCOL */ /* 20: CD_WEIGHT_MCOL */
{sizeof(MCol)*4, "MCol", 4, "WeightCol", NULL, NULL, layerInterp_mcol, {sizeof(MCol)*4, "MCol", 4, "WeightCol", NULL, NULL, layerInterp_mcol,
layerSwap_mcol, layerDefault_mcol}, layerSwap_mcol, layerDefault_mcol},
@ -867,6 +1036,30 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
/* 24: CD_RECAST */ /* 24: CD_RECAST */
{sizeof(MRecast), "MRecast", 1,"Recast",NULL,NULL,NULL,NULL} {sizeof(MRecast), "MRecast", 1,"Recast",NULL,NULL,NULL,NULL}
#ifdef USE_BMESH_FORWARD_COMPAT
,
/* BMESH ONLY */
/* 25: CD_MPOLY */
{sizeof(MPoly), "MPoly", 1, "NGon Face", NULL, NULL, NULL, NULL, NULL},
/* 26: CD_MLOOP */
{sizeof(MLoop), "MLoop", 1, "NGon Face-Vertex", NULL, NULL, NULL, NULL, NULL},
/* 27: CD_SHAPE_KEYINDEX */
{sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
/* 28: CD_SHAPEKEY */
{sizeof(float)*3, "", 0, "ShapeKey", NULL, NULL, layerInterp_shapekey},
/* 29: CD_BWEIGHT */
{sizeof(float), "", 0, "BevelWeight", NULL, NULL, layerInterp_bweight},
/* 30: CD_CREASE */
{sizeof(float), "", 0, "SubSurfCrease", NULL, NULL, layerInterp_bweight},
/* 31: CD_WEIGHT_MLOOPCOL */
{sizeof(MLoopCol), "MLoopCol", 1, "WeightLoopCol", NULL, NULL, layerInterp_mloopcol, NULL,
layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol,
layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol},
/* END BMESH ONLY */
#endif /* USE_BMESH_FORWARD_COMPAT */
}; };
static const char *LAYERTYPENAMES[CD_NUMTYPES] = { static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
@ -875,6 +1068,13 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
/* 10-14 */ "CDMFloatProperty", "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", /* 10-14 */ "CDMFloatProperty", "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco",
/* 15-19 */ "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent", "CDMDisps", /* 15-19 */ "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent", "CDMDisps",
/* 20-24 */"CDWeightMCol", "CDIDMCol", "CDTextureMCol", "CDClothOrco", "CDMRecast" /* 20-24 */"CDWeightMCol", "CDIDMCol", "CDTextureMCol", "CDClothOrco", "CDMRecast"
#ifdef USE_BMESH_FORWARD_COMPAT
,
/* 25-29 */ "CDMPoly", "CDMLoop", "CDShapeKeyIndex", "CDShapeKey", "CDBevelWeight",
/* 30-31 */ "CDSubSurfCrease", "CDWeightLoopCol"
#endif /* USE_BMESH_FORWARD_COMPAT */
}; };
const CustomDataMask CD_MASK_BAREMESH = const CustomDataMask CD_MASK_BAREMESH =
@ -896,7 +1096,6 @@ const CustomDataMask CD_MASK_FACECORNERS =
CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV | CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV |
CD_MASK_MLOOPCOL; CD_MASK_MLOOPCOL;
static const LayerTypeInfo *layerType_getInfo(int type) static const LayerTypeInfo *layerType_getInfo(int type)
{ {
if(type < 0 || type >= CD_NUMTYPES) return NULL; if(type < 0 || type >= CD_NUMTYPES) return NULL;
@ -917,6 +1116,25 @@ static void customData_update_offsets(CustomData *data);
static CustomDataLayer *customData_add_layer__internal(CustomData *data, static CustomDataLayer *customData_add_layer__internal(CustomData *data,
int type, int alloctype, void *layerdata, int totelem, const char *name); int type, int alloctype, void *layerdata, int totelem, const char *name);
void CustomData_update_typemap(CustomData *data)
{
int i, lasttype = -1;
/* since we cant do in a pre-processor do here as an assert */
BLI_assert(sizeof(data->typemap) / sizeof(int) >= CD_NUMTYPES);
for (i=0; i<CD_NUMTYPES; i++) {
data->typemap[i] = -1;
}
for (i=0; i<data->totlayer; i++) {
if (data->layers[i].type != lasttype) {
data->typemap[data->layers[i].type] = i;
}
lasttype = data->layers[i].type;
}
}
void CustomData_merge(const struct CustomData *source, struct CustomData *dest, void CustomData_merge(const struct CustomData *source, struct CustomData *dest,
CustomDataMask mask, int alloctype, int totelem) CustomDataMask mask, int alloctype, int totelem)
{ {
@ -961,6 +1179,8 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest,
newlayer->flag |= lastflag & (CD_FLAG_EXTERNAL|CD_FLAG_IN_MEMORY); newlayer->flag |= lastflag & (CD_FLAG_EXTERNAL|CD_FLAG_IN_MEMORY);
} }
} }
CustomData_update_typemap(dest);
} }
void CustomData_copy(const struct CustomData *source, struct CustomData *dest, void CustomData_copy(const struct CustomData *source, struct CustomData *dest,
@ -1025,6 +1245,7 @@ static void customData_update_offsets(CustomData *data)
} }
data->totsize = offset; data->totsize = offset;
CustomData_update_typemap(data);
} }
int CustomData_get_layer_index(const CustomData *data, int type) int CustomData_get_layer_index(const CustomData *data, int type)
@ -1038,6 +1259,17 @@ int CustomData_get_layer_index(const CustomData *data, int type)
return -1; return -1;
} }
int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n)
{
int i = CustomData_get_layer_index(data, type);
if (i != -1) {
i = (data->layers[i + n].type == type) ? (i + n) : (-1);
}
return i;
}
int CustomData_get_named_layer_index(const CustomData *data, int type, const char *name) int CustomData_get_named_layer_index(const CustomData *data, int type, const char *name)
{ {
int i; int i;
@ -1051,11 +1283,12 @@ int CustomData_get_named_layer_index(const CustomData *data, int type, const cha
int CustomData_get_active_layer_index(const CustomData *data, int type) int CustomData_get_active_layer_index(const CustomData *data, int type)
{ {
int i; if (!data->totlayer)
return -1;
for(i=0; i < data->totlayer; ++i) if (data->typemap[type] != -1) {
if(data->layers[i].type == type) return data->typemap[type] + data->layers[data->typemap[type]].active;
return i + data->layers[i].active; }
return -1; return -1;
} }
@ -1284,6 +1517,7 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
data->layers[index].type = type; data->layers[index].type = type;
data->layers[index].flag = flag; data->layers[index].flag = flag;
data->layers[index].data = newlayerdata; data->layers[index].data = newlayerdata;
if(name || (name=typeInfo->defaultname)) { if(name || (name=typeInfo->defaultname)) {
BLI_strncpy(data->layers[index].name, name, 32); BLI_strncpy(data->layers[index].name, name, 32);
CustomData_set_layer_unique_name(data, index); CustomData_set_layer_unique_name(data, index);
@ -1316,6 +1550,7 @@ void *CustomData_add_layer(CustomData *data, int type, int alloctype,
layer = customData_add_layer__internal(data, type, alloctype, layerdata, layer = customData_add_layer__internal(data, type, alloctype, layerdata,
totelem, typeInfo->defaultname); totelem, typeInfo->defaultname);
CustomData_update_typemap(data);
if(layer) if(layer)
return layer->data; return layer->data;
@ -1331,6 +1566,7 @@ void *CustomData_add_layer_named(CustomData *data, int type, int alloctype,
layer = customData_add_layer__internal(data, type, alloctype, layerdata, layer = customData_add_layer__internal(data, type, alloctype, layerdata,
totelem, name); totelem, name);
CustomData_update_typemap(data);
if(layer) if(layer)
return layer->data; return layer->data;
@ -1369,6 +1605,7 @@ int CustomData_free_layer(CustomData *data, int type, int totelem, int index)
customData_resize(data, -CUSTOMDATA_GROW); customData_resize(data, -CUSTOMDATA_GROW);
customData_update_offsets(data); customData_update_offsets(data);
CustomData_update_typemap(data);
return 1; return 1;
} }
@ -1469,6 +1706,20 @@ void *CustomData_duplicate_referenced_layer_named(struct CustomData *data,
return layer->data; return layer->data;
} }
int CustomData_is_referenced_layer(struct CustomData *data, int type)
{
CustomDataLayer *layer;
int layer_index;
/* get the layer index of the first layer of type */
layer_index = CustomData_get_active_layer_index(data, type);
if(layer_index < 0) return 0;
layer = &data->layers[layer_index];
return (layer->flag & CD_FLAG_NOFREE) != 0;
}
void CustomData_free_temporary(CustomData *data, int totelem) void CustomData_free_temporary(CustomData *data, int totelem)
{ {
CustomDataLayer *layer; CustomDataLayer *layer;
@ -1495,7 +1746,7 @@ void CustomData_free_temporary(CustomData *data, int totelem)
} }
void CustomData_set_only_copy(const struct CustomData *data, void CustomData_set_only_copy(const struct CustomData *data,
CustomDataMask mask) CustomDataMask mask)
{ {
int i; int i;
@ -1504,6 +1755,16 @@ void CustomData_set_only_copy(const struct CustomData *data,
data->layers[i].flag |= CD_FLAG_NOCOPY; data->layers[i].flag |= CD_FLAG_NOCOPY;
} }
void CustomData_copy_elements(int type, void *source, void *dest, int count)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
if (typeInfo->copy)
typeInfo->copy(source, dest, count);
else
memcpy(dest, source, typeInfo->size*count);
}
void CustomData_copy_data(const CustomData *source, CustomData *dest, void CustomData_copy_data(const CustomData *source, CustomData *dest,
int source_index, int dest_index, int count) int source_index, int dest_index, int count)
{ {
@ -1536,6 +1797,13 @@ void CustomData_copy_data(const CustomData *source, CustomData *dest,
src_offset = source_index * typeInfo->size; src_offset = source_index * typeInfo->size;
dest_offset = dest_index * typeInfo->size; dest_offset = dest_index * typeInfo->size;
if (!src_data || !dest_data) {
printf("%s: warning null data for %s type (%p --> %p), skipping\n",
__func__, layerType_getName(source->layers[src_i].type),
(void *)src_data, (void *)dest_data);
continue;
}
if(typeInfo->copy) if(typeInfo->copy)
typeInfo->copy(src_data + src_offset, typeInfo->copy(src_data + src_offset,
dest_data + dest_offset, dest_data + dest_offset,
@ -1663,6 +1931,19 @@ void *CustomData_get(const CustomData *data, int index, int type)
return (char *)data->layers[layer_index].data + offset; return (char *)data->layers[layer_index].data + offset;
} }
void *CustomData_get_n(const CustomData *data, int type, int index, int n)
{
int layer_index;
int offset;
/* get the layer index of the first layer of type */
layer_index = data->typemap[type];
if(layer_index < 0) return NULL;
offset = layerType_getInfo(type)->size * index;
return (char *)data->layers[layer_index+n].data + offset;
}
void *CustomData_get_layer(const CustomData *data, int type) void *CustomData_get_layer(const CustomData *data, int type)
{ {
/* get the layer index of the active layer of type */ /* get the layer index of the active layer of type */
@ -1675,10 +1956,10 @@ void *CustomData_get_layer(const CustomData *data, int type)
void *CustomData_get_layer_n(const CustomData *data, int type, int n) void *CustomData_get_layer_n(const CustomData *data, int type, int n)
{ {
/* get the layer index of the active layer of type */ /* get the layer index of the active layer of type */
int layer_index = CustomData_get_layer_index(data, type); int layer_index = CustomData_get_layer_index_n(data, type, n);
if(layer_index < 0) return NULL; if(layer_index < 0) return NULL;
return data->layers[layer_index+n].data; return data->layers[layer_index].data;
} }
void *CustomData_get_layer_named(const struct CustomData *data, int type, void *CustomData_get_layer_named(const struct CustomData *data, int type,
@ -1690,6 +1971,20 @@ void *CustomData_get_layer_named(const struct CustomData *data, int type,
return data->layers[layer_index].data; return data->layers[layer_index].data;
} }
int CustomData_set_layer_name(const CustomData *data, int type, int n, const char *name)
{
/* get the layer index of the first layer of type */
int layer_index = CustomData_get_layer_index_n(data, type, n);
if(layer_index < 0) return 0;
if (!name) return 0;
strcpy(data->layers[layer_index].name, name);
return 1;
}
void *CustomData_set_layer(const CustomData *data, int type, void *ptr) void *CustomData_set_layer(const CustomData *data, int type, void *ptr)
{ {
/* get the layer index of the first layer of type */ /* get the layer index of the first layer of type */
@ -1705,10 +2000,10 @@ void *CustomData_set_layer(const CustomData *data, int type, void *ptr)
void *CustomData_set_layer_n(const struct CustomData *data, int type, int n, void *ptr) void *CustomData_set_layer_n(const struct CustomData *data, int type, int n, void *ptr)
{ {
/* get the layer index of the first layer of type */ /* get the layer index of the first layer of type */
int layer_index = CustomData_get_layer_index(data, type); int layer_index = CustomData_get_layer_index_n(data, type, n);
if(layer_index < 0) return NULL; if(layer_index < 0) return NULL;
data->layers[layer_index+n].data = ptr; data->layers[layer_index].data = ptr;
return ptr; return ptr;
} }
@ -1836,10 +2131,10 @@ void *CustomData_em_get_n(const CustomData *data, void *block, int type, int n)
int layer_index; int layer_index;
/* get the layer index of the first layer of type */ /* get the layer index of the first layer of type */
layer_index = CustomData_get_layer_index(data, type); layer_index = CustomData_get_layer_index_n(data, type, n);
if(layer_index < 0) return NULL; if(layer_index < 0) return NULL;
return (char *)block + data->layers[layer_index+n].offset; return (char *)block + data->layers[layer_index].offset;
} }
void CustomData_em_set(CustomData *data, void *block, int type, void *source) void CustomData_em_set(CustomData *data, void *block, int type, void *source)
@ -2141,6 +2436,15 @@ void *CustomData_bmesh_get_n(const CustomData *data, void *block, int type, int
return (char *)block + data->layers[layer_index+n].offset; return (char *)block + data->layers[layer_index+n].offset;
} }
/*gets from the layer at physical index n, note: doesn't check type.*/
void *CustomData_bmesh_get_layer_n(const CustomData *data, void *block, int n)
{
if(n < 0 || n >= data->totlayer) return NULL;
return (char *)block + data->layers[n].offset;
}
void CustomData_bmesh_set(const CustomData *data, void *block, int type, void *source) void CustomData_bmesh_set(const CustomData *data, void *block, int type, void *source)
{ {
void *dest = CustomData_bmesh_get(data, block, type); void *dest = CustomData_bmesh_get(data, block, type);
@ -2167,6 +2471,19 @@ void CustomData_bmesh_set_n(CustomData *data, void *block, int type, int n, void
memcpy(dest, source, typeInfo->size); memcpy(dest, source, typeInfo->size);
} }
void CustomData_bmesh_set_layer_n(CustomData *data, void *block, int n, void *source)
{
void *dest = CustomData_bmesh_get_layer_n(data, block, n);
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[n].type);
if(!dest) return;
if(typeInfo->copy)
typeInfo->copy(source, dest, 1);
else
memcpy(dest, source, typeInfo->size);
}
void CustomData_bmesh_interp(CustomData *data, void **src_blocks, float *weights, void CustomData_bmesh_interp(CustomData *data, void **src_blocks, float *weights,
float *sub_weights, int count, void *dest_block) float *sub_weights, int count, void *dest_block)
{ {
@ -2212,6 +2529,7 @@ void CustomData_bmesh_set_default(CustomData *data, void **block)
if(typeInfo->set_default) if(typeInfo->set_default)
typeInfo->set_default((char*)*block + offset, 1); typeInfo->set_default((char*)*block + offset, 1);
else memset((char*)*block + offset, 0, typeInfo->size);
} }
} }

@ -269,7 +269,8 @@ DagNode * pop_queue(DagNodeQueue *queue)
} }
} }
void *pop_ob_queue(struct DagNodeQueue *queue) { void *pop_ob_queue(struct DagNodeQueue *queue)
{
return(pop_queue(queue)->ob); return(pop_queue(queue)->ob);
} }
@ -278,7 +279,8 @@ DagNode * get_top_node_queue(DagNodeQueue *queue)
return queue->first->node; return queue->first->node;
} }
int queue_count(struct DagNodeQueue *queue){ int queue_count(struct DagNodeQueue *queue)
{
return queue->count; return queue->count;
} }
@ -647,16 +649,21 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
continue; continue;
/* special case for camera tracking -- it doesn't use targets to define relations */ /* special case for camera tracking -- it doesn't use targets to define relations */
if(ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER)) { if(ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
int depends_on_camera= 0;
if(cti->type==CONSTRAINT_TYPE_FOLLOWTRACK) { if(cti->type==CONSTRAINT_TYPE_FOLLOWTRACK) {
bFollowTrackConstraint *data= (bFollowTrackConstraint *)con->data; bFollowTrackConstraint *data= (bFollowTrackConstraint *)con->data;
if((data->clip || data->flag&FOLLOWTRACK_ACTIVECLIP) && data->track[0]) { if((data->clip || data->flag&FOLLOWTRACK_ACTIVECLIP) && data->track[0])
if(scene->camera) { depends_on_camera= 1;
node2 = dag_get_node(dag, scene->camera); }
dag_add_relation(dag, node2, node, DAG_RL_DATA_OB|DAG_RL_OB_OB, cti->name); else if(cti->type==CONSTRAINT_TYPE_OBJECTSOLVER)
} depends_on_camera= 1;
}
if(depends_on_camera && scene->camera) {
node2 = dag_get_node(dag, scene->camera);
dag_add_relation(dag, node2, node, DAG_RL_DATA_OB|DAG_RL_OB_OB, cti->name);
} }
dag_add_relation(dag,scenenode,node,DAG_RL_SCENE, "Scene Relation"); dag_add_relation(dag,scenenode,node,DAG_RL_SCENE, "Scene Relation");
@ -1155,7 +1162,8 @@ void graph_bfs(void)
queue_delete(nqueue); queue_delete(nqueue);
} }
int pre_and_post_BFS(DagForest *dag, short mask, graph_action_func pre_func, graph_action_func post_func, void **data) { int pre_and_post_BFS(DagForest *dag, short mask, graph_action_func pre_func, graph_action_func post_func, void **data)
{
DagNode *node; DagNode *node;
node = dag->DagNode.first; node = dag->DagNode.first;
@ -1341,7 +1349,8 @@ DagNodeQueue * graph_dfs(void)
} }
/* unused */ /* unused */
int pre_and_post_DFS(DagForest *dag, short mask, graph_action_func pre_func, graph_action_func post_func, void **data) { int pre_and_post_DFS(DagForest *dag, short mask, graph_action_func pre_func, graph_action_func post_func, void **data)
{
DagNode *node; DagNode *node;
node = dag->DagNode.first; node = dag->DagNode.first;
@ -1552,7 +1561,8 @@ struct DagNodeQueue *get_all_childs(struct DagForest *dag, void *ob)
} }
/* unused */ /* unused */
short are_obs_related(struct DagForest *dag, void *ob1, void *ob2) { short are_obs_related(struct DagForest *dag, void *ob1, void *ob2)
{
DagNode * node; DagNode * node;
DagAdjList *itA; DagAdjList *itA;
@ -1568,7 +1578,8 @@ short are_obs_related(struct DagForest *dag, void *ob1, void *ob2) {
return DAG_NO_RELATION; return DAG_NO_RELATION;
} }
int is_acyclic( DagForest *dag) { int is_acyclic( DagForest *dag)
{
return dag->is_acyclic; return dag->is_acyclic;
} }
@ -2159,7 +2170,7 @@ static void dag_object_time_update_flags(Object *ob)
if (cti) { if (cti) {
/* special case for camera tracking -- it doesn't use targets to define relations */ /* special case for camera tracking -- it doesn't use targets to define relations */
if(ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER)) { if(ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
ob->recalc |= OB_RECALC_OB; ob->recalc |= OB_RECALC_OB;
} }
else if (cti->get_constraint_targets) { else if (cti->get_constraint_targets) {
@ -2553,7 +2564,9 @@ static void dag_id_flush_update(Scene *sce, ID *id)
bConstraint *con; bConstraint *con;
for (con = obt->constraints.first; con; con=con->next) { for (con = obt->constraints.first; con; con=con->next) {
bConstraintTypeInfo *cti= constraint_get_typeinfo(con); bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
if(ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER)) { if(ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER,
CONSTRAINT_TYPE_OBJECTSOLVER))
{
obt->recalc |= OB_RECALC_OB; obt->recalc |= OB_RECALC_OB;
break; break;
} }

@ -510,8 +510,6 @@ static void scene_setSubframe(Scene *scene, float subframe)
scene->r.subframe = subframe; scene->r.subframe = subframe;
} }
#define BRUSH_USES_VELOCITY (1<<0)
static int surface_getBrushFlags(DynamicPaintSurface *surface, Scene *scene) static int surface_getBrushFlags(DynamicPaintSurface *surface, Scene *scene)
{ {
Base *base = NULL; Base *base = NULL;
@ -2291,7 +2289,7 @@ int dynamicPaint_createUVSurface(DynamicPaintSurface *surface)
tPoint->quad = (isInside == 2) ? 1 : 0; /* quad or tri part*/ tPoint->quad = (isInside == 2) ? 1 : 0; /* quad or tri part*/
/* save vertex indexes */ /* save vertex indexes */
tPoint->v1 = mface[i].v1; /* (isInside == 2) ? mface[i].v1 : mface[i].v1; */ /* same! */ tPoint->v1 = mface[i].v1;
tPoint->v2 = (isInside == 2) ? mface[i].v3 : mface[i].v2; tPoint->v2 = (isInside == 2) ? mface[i].v3 : mface[i].v2;
tPoint->v3 = (isInside == 2) ? mface[i].v4 : mface[i].v3; tPoint->v3 = (isInside == 2) ? mface[i].v4 : mface[i].v3;
@ -2371,7 +2369,7 @@ int dynamicPaint_createUVSurface(DynamicPaintSurface *surface)
tPoint->quad = tempPoints[ind].quad; // quad or tri tPoint->quad = tempPoints[ind].quad; // quad or tri
/* save vertex indexes */ /* save vertex indexes */
tPoint->v1 = (tPoint->quad) ? mface[i].v1 : mface[i].v1; tPoint->v1 = mface[i].v1;
tPoint->v2 = (tPoint->quad) ? mface[i].v3 : mface[i].v2; tPoint->v2 = (tPoint->quad) ? mface[i].v3 : mface[i].v2;
tPoint->v3 = (tPoint->quad) ? mface[i].v4 : mface[i].v3; tPoint->v3 = (tPoint->quad) ? mface[i].v4 : mface[i].v3;
@ -2401,10 +2399,8 @@ int dynamicPaint_createUVSurface(DynamicPaintSurface *surface)
} }
} }
/* If any effect enabled, create surface effect / wet layer /* Generate surface adjacency data. */
* neighbour lists. Processes possibly moving data. */ {
if (surface_usesAdjData(surface)) {
int i, cursor=0; int i, cursor=0;
/* Create a temporary array of final indexes (before unassigned /* Create a temporary array of final indexes (before unassigned
@ -2417,12 +2413,11 @@ int dynamicPaint_createUVSurface(DynamicPaintSurface *surface)
} }
/* allocate memory */ /* allocate memory */
sData->total_points = w*h; sData->total_points = w*h;
dynamicPaint_initAdjacencyData(surface, 0); dynamicPaint_initAdjacencyData(surface, 1);
if (sData->adj_data) { if (sData->adj_data) {
PaintAdjData *ed = sData->adj_data; PaintAdjData *ed = sData->adj_data;
unsigned int n_pos = 0; unsigned int n_pos = 0;
//#pragma omp parallel for schedule(static)
for (ty = 0; ty < h; ty++) for (ty = 0; ty < h; ty++)
{ {
int tx; int tx;

@ -285,6 +285,10 @@ static void image_assign_ibuf(Image *ima, ImBuf *ibuf, int index, int frame)
break; break;
ibuf->index= index; ibuf->index= index;
if(ima->flag & IMA_CM_PREDIVIDE)
ibuf->flags |= IB_cm_predivide;
else
ibuf->flags &= ~IB_cm_predivide;
/* this function accepts link==NULL */ /* this function accepts link==NULL */
BLI_insertlinkbefore(&ima->ibufs, link, ibuf); BLI_insertlinkbefore(&ima->ibufs, link, ibuf);
@ -2304,9 +2308,17 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_
/* since its possible to access the buffer from the image directly, set the profile [#25073] */ /* since its possible to access the buffer from the image directly, set the profile [#25073] */
ibuf->profile= (iuser->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_NONE; ibuf->profile= (iuser->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_NONE;
ibuf->dither= dither; ibuf->dither= dither;
if(iuser->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE) {
ibuf->flags |= IB_cm_predivide;
ima->flag |= IMA_CM_PREDIVIDE;
}
else {
ibuf->flags &= ~IB_cm_predivide;
ima->flag &= ~IMA_CM_PREDIVIDE;
}
ima->ok= IMA_OK_LOADED; ima->ok= IMA_OK_LOADED;
return ibuf; return ibuf;

@ -65,6 +65,10 @@
/* -- */ /* -- */
#include "BKE_object.h" #include "BKE_object.h"
#ifdef USE_BMESH_FORWARD_COMPAT
#include "BLI_array.h"
#endif
EditMesh *BKE_mesh_get_editmesh(Mesh *me) EditMesh *BKE_mesh_get_editmesh(Mesh *me)
{ {
@ -366,9 +370,9 @@ void mesh_get_texspace(Mesh *me, float *loc_r, float *rot_r, float *size_r)
tex_space_mesh(me); tex_space_mesh(me);
} }
if (loc_r) VECCOPY(loc_r, me->loc); if (loc_r) copy_v3_v3(loc_r, me->loc);
if (rot_r) VECCOPY(rot_r, me->rot); if (rot_r) copy_v3_v3(rot_r, me->rot);
if (size_r) VECCOPY(size_r, me->size); if (size_r) copy_v3_v3(size_r, me->size);
} }
float *get_mesh_orco_verts(Object *ob) float *get_mesh_orco_verts(Object *ob)
@ -726,7 +730,7 @@ void mball_to_mesh(ListBase *lb, Mesh *me)
nors= dl->nors; nors= dl->nors;
verts= dl->verts; verts= dl->verts;
while(a--) { while(a--) {
VECCOPY(mvert->co, verts); copy_v3_v3(mvert->co, verts);
normal_float_to_short_v3(mvert->no, nors); normal_float_to_short_v3(mvert->no, nors);
mvert++; mvert++;
nors+= 3; nors+= 3;
@ -825,7 +829,7 @@ int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int
a= dl->parts*dl->nr; a= dl->parts*dl->nr;
data= dl->verts; data= dl->verts;
while(a--) { while(a--) {
VECCOPY(mvert->co, data); copy_v3_v3(mvert->co, data);
data+=3; data+=3;
vertcount++; vertcount++;
mvert++; mvert++;
@ -848,7 +852,7 @@ int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int
a= dl->parts*dl->nr; a= dl->parts*dl->nr;
data= dl->verts; data= dl->verts;
while(a--) { while(a--) {
VECCOPY(mvert->co, data); copy_v3_v3(mvert->co, data);
data+=3; data+=3;
vertcount++; vertcount++;
mvert++; mvert++;
@ -871,7 +875,7 @@ int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int
a= dl->nr; a= dl->nr;
data= dl->verts; data= dl->verts;
while(a--) { while(a--) {
VECCOPY(mvert->co, data); copy_v3_v3(mvert->co, data);
data+=3; data+=3;
vertcount++; vertcount++;
mvert++; mvert++;
@ -899,7 +903,7 @@ int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int
a= dl->parts*dl->nr; a= dl->parts*dl->nr;
data= dl->verts; data= dl->verts;
while(a--) { while(a--) {
VECCOPY(mvert->co, data); copy_v3_v3(mvert->co, data);
data+=3; data+=3;
vertcount++; vertcount++;
mvert++; mvert++;
@ -988,8 +992,8 @@ void nurbs_to_mesh(Object *ob)
me->totedge= totedge; me->totedge= totedge;
me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, allvert, me->totvert); me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, allvert, me->totvert);
me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, allface, me->totface);
me->medge= CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, alledge, me->totedge); me->medge= CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, alledge, me->totedge);
me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, allface, me->totface);
mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL); mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
} else { } else {
@ -1445,6 +1449,184 @@ void create_vert_edge_map(ListBase **map, IndexNode **mem, const MEdge *medge, c
} }
} }
#ifdef USE_BMESH_FORWARD_COMPAT
void mesh_loops_to_mface_corners(CustomData *fdata, CustomData *ldata,
CustomData *pdata, int lindex[4], int findex,
const int polyindex,
const int mf_len, /* 3 or 4 */
/* cache values to avoid lookups every time */
const int numTex, /* CustomData_number_of_layers(pdata, CD_MTEXPOLY) */
const int numCol, /* CustomData_number_of_layers(ldata, CD_MLOOPCOL) */
const int hasWCol /* CustomData_has_layer(ldata, CD_WEIGHT_MLOOPCOL) */
)
{
MTFace *texface;
MTexPoly *texpoly;
MCol *mcol;
MLoopCol *mloopcol;
MLoopUV *mloopuv;
int i, j;
for(i=0; i < numTex; i++){
texface = CustomData_get_n(fdata, CD_MTFACE, findex, i);
texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, polyindex, i);
texface->tpage = texpoly->tpage;
texface->flag = texpoly->flag;
texface->transp = texpoly->transp;
texface->mode = texpoly->mode;
texface->tile = texpoly->tile;
texface->unwrap = texpoly->unwrap;
for (j=0; j < mf_len; j++) {
mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, lindex[j], i);
texface->uv[j][0] = mloopuv->uv[0];
texface->uv[j][1] = mloopuv->uv[1];
}
}
for(i=0; i < numCol; i++){
mcol = CustomData_get_n(fdata, CD_MCOL, findex, i);
for (j=0; j < mf_len; j++) {
mloopcol = CustomData_get_n(ldata, CD_MLOOPCOL, lindex[j], i);
mcol[j].r = mloopcol->r;
mcol[j].g = mloopcol->g;
mcol[j].b = mloopcol->b;
mcol[j].a = mloopcol->a;
}
}
if (hasWCol) {
mcol = CustomData_get(fdata, findex, CD_WEIGHT_MCOL);
for (j=0; j < mf_len; j++) {
mloopcol = CustomData_get(ldata, lindex[j], CD_WEIGHT_MLOOPCOL);
mcol[j].r = mloopcol->r;
mcol[j].g = mloopcol->g;
mcol[j].b = mloopcol->b;
mcol[j].a = mloopcol->a;
}
}
}
/*
* this function recreates a tesselation.
* returns number of tesselation faces.
*/
int mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata,
struct CustomData *pdata, int totface, int UNUSED(totloop), int totpoly)
{
MLoop *mloop;
int lindex[4];
int i;
int k;
MPoly *mp, *mpoly;
MFace *mface = NULL, *mf;
BLI_array_declare(mface);
const int numTex = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
const int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
const int hasWCol = CustomData_has_layer(ldata, CD_WEIGHT_MLOOPCOL);
mpoly = CustomData_get_layer(pdata, CD_MPOLY);
mloop = CustomData_get_layer(ldata, CD_MLOOP);
mp = mpoly;
k = 0;
for (i = 0; i<totpoly; i++, mp++) {
if (ELEM(mp->totloop, 3, 4)) {
BLI_array_growone(mface);
mf = &mface[k];
mf->mat_nr = mp->mat_nr;
mf->flag = mp->flag;
mf->v1 = mp->loopstart + 0;
mf->v2 = mp->loopstart + 1;
mf->v3 = mp->loopstart + 2;
mf->v4 = (mp->totloop == 4) ? (mp->loopstart + 3) : 0;
/* abuse edcode for temp storage and clear next loop */
mf->edcode = (char)mp->totloop; /* only ever 3 or 4 */
k++;
}
}
CustomData_free(fdata, totface);
memset(fdata, 0, sizeof(CustomData));
totface= k;
CustomData_add_layer(fdata, CD_MFACE, CD_ASSIGN, mface, totface);
CustomData_from_bmeshpoly(fdata, pdata, ldata, totface);
mp = mpoly;
k = 0;
for (i = 0; i<totpoly; i++, mp++) {
if (ELEM(mp->totloop, 3, 4)) {
mf = &mface[k];
if (mf->edcode == 3) {
/*sort loop indices to ensure winding is correct*/
/* NO SORT - looks like we can skip this */
lindex[0] = mf->v1;
lindex[1] = mf->v2;
lindex[2] = mf->v3;
lindex[3] = 0; /* unused */
/*transform loop indices to vert indices*/
mf->v1 = mloop[mf->v1].v;
mf->v2 = mloop[mf->v2].v;
mf->v3 = mloop[mf->v3].v;
mesh_loops_to_mface_corners(fdata, ldata, pdata,
lindex, k, i, 3,
numTex, numCol, hasWCol);
test_index_face(mf, fdata, totface, 3);
}
else {
/*sort loop indices to ensure winding is correct*/
/* NO SORT - looks like we can skip this */
lindex[0] = mf->v1;
lindex[1] = mf->v2;
lindex[2] = mf->v3;
lindex[3] = mf->v4;
/*transform loop indices to vert indices*/
mf->v1 = mloop[mf->v1].v;
mf->v2 = mloop[mf->v2].v;
mf->v3 = mloop[mf->v3].v;
mf->v4 = mloop[mf->v4].v;
mesh_loops_to_mface_corners(fdata, ldata, pdata,
lindex, k, i, 4,
numTex, numCol, hasWCol);
test_index_face(mf, fdata, totface, 4);
}
mf->edcode= 0;
k++;
}
}
return k;
}
#endif /* USE_BMESH_FORWARD_COMPAT */
/* basic vertex data functions */ /* basic vertex data functions */
int minmax_mesh(Mesh *me, float min[3], float max[3]) int minmax_mesh(Mesh *me, float min[3], float max[3])
{ {

@ -509,7 +509,7 @@ void BKE_mesh_calc_edges(Mesh *mesh, int update)
if(update && (med_orig=BLI_edgehashIterator_getValue(ehi))) { if(update && (med_orig=BLI_edgehashIterator_getValue(ehi))) {
*med= *med_orig; /* copy from the original */ *med= *med_orig; /* copy from the original */
} else { } else {
BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2); BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2);
med->flag = ME_EDGEDRAW|ME_EDGERENDER|SELECT; /* select for newly created meshes which are selected [#25595] */ med->flag = ME_EDGEDRAW|ME_EDGERENDER|SELECT; /* select for newly created meshes which are selected [#25595] */
} }
} }

@ -816,7 +816,8 @@ void BKE_movieclip_reload(MovieClip *clip)
void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClipScopes *scopes) void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClipScopes *scopes)
{ {
if(scopes->ok) return; if(scopes->ok)
return;
if(scopes->track_preview) { if(scopes->track_preview) {
IMB_freeImBuf(scopes->track_preview); IMB_freeImBuf(scopes->track_preview);
@ -827,8 +828,10 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip
scopes->track= NULL; scopes->track= NULL;
if(clip) { if(clip) {
if(clip->tracking.act_track) { MovieTrackingTrack *act_track= BKE_tracking_active_track(&clip->tracking);
MovieTrackingTrack *track= clip->tracking.act_track;
if(act_track) {
MovieTrackingTrack *track= act_track;
MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr); MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
if(marker->flag&MARKER_DISABLED) { if(marker->flag&MARKER_DISABLED) {

@ -90,7 +90,8 @@ static void do_child_modifiers(ParticleSimulationData *sim,
float *orco, float mat[4][4], ParticleKey *state, float t); float *orco, float mat[4][4], ParticleKey *state, float t);
/* few helpers for countall etc. */ /* few helpers for countall etc. */
int count_particles(ParticleSystem *psys){ int count_particles(ParticleSystem *psys)
{
ParticleSettings *part=psys->part; ParticleSettings *part=psys->part;
PARTICLE_P; PARTICLE_P;
int tot=0; int tot=0;
@ -102,7 +103,8 @@ int count_particles(ParticleSystem *psys){
} }
return tot; return tot;
} }
int count_particles_mod(ParticleSystem *psys, int totgr, int cur){ int count_particles_mod(ParticleSystem *psys, int totgr, int cur)
{
ParticleSettings *part=psys->part; ParticleSettings *part=psys->part;
PARTICLE_P; PARTICLE_P;
int tot=0; int tot=0;
@ -1123,7 +1125,8 @@ static int get_pointcache_times_for_particle(PointCache *cache, int index, float
return ret == 2; return ret == 2;
} }
float psys_get_dietime_from_cache(PointCache *cache, int index) { float psys_get_dietime_from_cache(PointCache *cache, int index)
{
PTCacheMem *pm; PTCacheMem *pm;
int dietime = 10000000; /* some max value so that we can default to pa->time+lifetime */ int dietime = 10000000; /* some max value so that we can default to pa->time+lifetime */
@ -1366,7 +1369,9 @@ static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData
/* Particles on a dm */ /* Particles on a dm */
/************************************************/ /************************************************/
/* interpolate a location on a face based on face coordinates */ /* interpolate a location on a face based on face coordinates */
void psys_interpolate_face(MVert *mvert, MFace *mface, MTFace *tface, float (*orcodata)[3], float *w, float *vec, float *nor, float *utan, float *vtan, float *orco,float *ornor){ void psys_interpolate_face(MVert *mvert, MFace *mface, MTFace *tface, float (*orcodata)[3],
float *w, float *vec, float *nor, float *utan, float *vtan, float *orco,float *ornor)
{
float *v1=0, *v2=0, *v3=0, *v4=0; float *v1=0, *v2=0, *v3=0, *v4=0;
float e1[3],e2[3],s1,s2,t1,t2; float e1[3],e2[3],s1,s2,t1,t2;
float *uv1, *uv2, *uv3, *uv4; float *uv1, *uv2, *uv3, *uv4;
@ -1828,7 +1833,8 @@ static void psys_particle_on_shape(int UNUSED(distr), int UNUSED(index), float *
/************************************************/ /************************************************/
/* Particles on emitter */ /* Particles on emitter */
/************************************************/ /************************************************/
void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor){ void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor)
{
if(psmd){ if(psmd){
if(psmd->psys->part->distr==PART_DISTR_GRID && psmd->psys->part->from != PART_FROM_VERT){ if(psmd->psys->part->distr==PART_DISTR_GRID && psmd->psys->part->from != PART_FROM_VERT){
if(vec) if(vec)
@ -3231,7 +3237,8 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
/************************************************/ /************************************************/
/* Particle Key handling */ /* Particle Key handling */
/************************************************/ /************************************************/
void copy_particle_key(ParticleKey *to, ParticleKey *from, int time){ void copy_particle_key(ParticleKey *to, ParticleKey *from, int time)
{
if(time){ if(time){
memcpy(to,from,sizeof(ParticleKey)); memcpy(to,from,sizeof(ParticleKey));
} }
@ -3241,7 +3248,8 @@ void copy_particle_key(ParticleKey *to, ParticleKey *from, int time){
to->time=to_time; to->time=to_time;
} }
} }
void psys_get_from_key(ParticleKey *key, float *loc, float *vel, float *rot, float *time){ void psys_get_from_key(ParticleKey *key, float *loc, float *vel, float *rot, float *time)
{
if(loc) copy_v3_v3(loc,key->co); if(loc) copy_v3_v3(loc,key->co);
if(vel) copy_v3_v3(vel,key->vel); if(vel) copy_v3_v3(vel,key->vel);
if(rot) copy_qt_qt(rot,key->rot); if(rot) copy_qt_qt(rot,key->rot);
@ -3249,7 +3257,8 @@ void psys_get_from_key(ParticleKey *key, float *loc, float *vel, float *rot, flo
} }
/*-------changing particle keys from space to another-------*/ /*-------changing particle keys from space to another-------*/
#if 0 #if 0
static void key_from_object(Object *ob, ParticleKey *key){ static void key_from_object(Object *ob, ParticleKey *key)
{
float q[4]; float q[4];
add_v3_v3(key->vel, key->co); add_v3_v3(key->vel, key->co);
@ -4177,7 +4186,8 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
} }
} }
/* gets particle's state at a time, returns 1 if particle exists and can be seen and 0 if not */ /* gets particle's state at a time, returns 1 if particle exists and can be seen and 0 if not */
int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *state, int always){ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *state, int always)
{
ParticleSystem *psys = sim->psys; ParticleSystem *psys = sim->psys;
ParticleSettings *part = psys->part; ParticleSettings *part = psys->part;
ParticleData *pa = NULL; ParticleData *pa = NULL;
@ -4515,7 +4525,8 @@ void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3]
} }
void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys) { void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys)
{
ParticleSimulationData sim= {0}; ParticleSimulationData sim= {0};
sim.scene= scene; sim.scene= scene;
sim.ob= ob; sim.ob= ob;

@ -107,7 +107,8 @@
/* Reacting to system events */ /* Reacting to system events */
/************************************************/ /************************************************/
static int particles_are_dynamic(ParticleSystem *psys) { static int particles_are_dynamic(ParticleSystem *psys)
{
if(psys->pointcache->flag & PTCACHE_BAKED) if(psys->pointcache->flag & PTCACHE_BAKED)
return 0; return 0;
@ -2240,7 +2241,8 @@ static void sph_spring_delete(ParticleSystem *psys, int j)
psys->fluid_springs = (ParticleSpring*)MEM_reallocN(psys->fluid_springs, psys->alloc_fluidsprings * sizeof(ParticleSpring)); psys->fluid_springs = (ParticleSpring*)MEM_reallocN(psys->fluid_springs, psys->alloc_fluidsprings * sizeof(ParticleSpring));
} }
} }
static void sph_springs_modify(ParticleSystem *psys, float dtime){ static void sph_springs_modify(ParticleSystem *psys, float dtime)
{
SPHFluidSettings *fluid = psys->part->fluid; SPHFluidSettings *fluid = psys->part->fluid;
ParticleData *pa1, *pa2; ParticleData *pa1, *pa2;
ParticleSpring *spring = psys->fluid_springs; ParticleSpring *spring = psys->fluid_springs;
@ -2490,7 +2492,8 @@ static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, floa
madd_v3_v3fl(force, gravity, fluid->buoyancy * (pfr.density-rest_density)); madd_v3_v3fl(force, gravity, fluid->buoyancy * (pfr.density-rest_density));
} }
static void sph_integrate(ParticleSimulationData *sim, ParticleData *pa, float dfra, float *gravity, EdgeHash *springhash, float *element_size, float flow[3]) { static void sph_integrate(ParticleSimulationData *sim, ParticleData *pa, float dfra, float *gravity, EdgeHash *springhash, float *element_size, float flow[3])
{
ParticleTarget *pt; ParticleTarget *pt;
int i; int i;
@ -3293,7 +3296,8 @@ static void collision_fail(ParticleData *pa, ParticleCollision *col)
* -uses Newton-Rhapson iteration to find the collisions * -uses Newton-Rhapson iteration to find the collisions
* -handles spherical particles and (nearly) point like particles * -handles spherical particles and (nearly) point like particles
*/ */
static void collision_check(ParticleSimulationData *sim, int p, float dfra, float cfra){ static void collision_check(ParticleSimulationData *sim, int p, float dfra, float cfra)
{
ParticleSettings *part = sim->psys->part; ParticleSettings *part = sim->psys->part;
ParticleData *pa = sim->psys->particles + p; ParticleData *pa = sim->psys->particles + p;
ParticleCollision col; ParticleCollision col;
@ -3561,7 +3565,8 @@ static void hair_step(ParticleSimulationData *sim, float cfra)
psys->flag |= PSYS_HAIR_UPDATED; psys->flag |= PSYS_HAIR_UPDATED;
} }
static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra)){ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra))
{
Object *ob = sim->ob; Object *ob = sim->ob;
ParticleSystem *psys = sim->psys; ParticleSystem *psys = sim->psys;
HairKey *key, *root; HairKey *key, *root;
@ -4241,7 +4246,8 @@ void psys_check_boid_data(ParticleSystem *psys)
} }
} }
static void fluid_default_settings(ParticleSettings *part){ static void fluid_default_settings(ParticleSettings *part)
{
SPHFluidSettings *fluid = part->fluid; SPHFluidSettings *fluid = part->fluid;
fluid->spring_k = 0.f; fluid->spring_k = 0.f;

@ -2025,7 +2025,10 @@ static ImBuf * seq_render_scene_strip_impl(
} }
/* float buffers in the sequencer are not linear */ /* float buffers in the sequencer are not linear */
ibuf->profile= IB_PROFILE_LINEAR_RGB; if(scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)
ibuf->profile= IB_PROFILE_LINEAR_RGB;
else
ibuf->profile= IB_PROFILE_NONE;
IMB_convert_profile(ibuf, IB_PROFILE_SRGB); IMB_convert_profile(ibuf, IB_PROFILE_SRGB);
} }
else if (rres.rect32) { else if (rres.rect32) {

@ -55,6 +55,7 @@
#include "BKE_movieclip.h" #include "BKE_movieclip.h"
#include "BKE_object.h" #include "BKE_object.h"
#include "BKE_scene.h" #include "BKE_scene.h"
#include "BKE_main.h" // XXX: ...
#include "IMB_imbuf_types.h" #include "IMB_imbuf_types.h"
#include "IMB_imbuf.h" #include "IMB_imbuf.h"
@ -85,11 +86,14 @@ void BKE_tracking_init_settings(MovieTracking *tracking)
tracking->settings.keyframe1= 1; tracking->settings.keyframe1= 1;
tracking->settings.keyframe2= 30; tracking->settings.keyframe2= 30;
tracking->settings.dist= 1; tracking->settings.dist= 1;
tracking->settings.object_distance= 1;
tracking->stabilization.scaleinf= 1.0f; tracking->stabilization.scaleinf= 1.0f;
tracking->stabilization.locinf= 1.0f; tracking->stabilization.locinf= 1.0f;
tracking->stabilization.rotinf= 1.0f; tracking->stabilization.rotinf= 1.0f;
tracking->stabilization.maxscale= 2.0f; tracking->stabilization.maxscale= 2.0f;
BKE_tracking_new_object(tracking, "Camera");
} }
void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event) void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event)
@ -208,7 +212,7 @@ void BKE_tracking_track_flag(MovieTrackingTrack *track, int area, int flag, int
} }
} }
MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, float x, float y, MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, ListBase *tracksbase, float x, float y,
int framenr, int width, int height) int framenr, int width, int height)
{ {
MovieTrackingTrack *track; MovieTrackingTrack *track;
@ -251,8 +255,8 @@ MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, float x, flo
if(track->tracker == TRACKER_KLT) if(track->tracker == TRACKER_KLT)
BKE_tracking_clamp_track(track, CLAMP_PYRAMID_LEVELS); BKE_tracking_clamp_track(track, CLAMP_PYRAMID_LEVELS);
BLI_addtail(&tracking->tracks, track); BLI_addtail(tracksbase, track);
BKE_track_unique_name(tracking, track); BKE_track_unique_name(tracksbase, track);
return track; return track;
} }
@ -524,18 +528,44 @@ void BKE_tracking_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack
dst_track->markersnr= tot; dst_track->markersnr= tot;
} }
void BKE_tracking_free(MovieTracking *tracking) static void tracking_tracks_free(ListBase *tracks)
{ {
MovieTrackingTrack *track; MovieTrackingTrack *track;
for(track= tracking->tracks.first; track; track= track->next) { for(track= tracks->first; track; track= track->next) {
BKE_tracking_free_track(track); BKE_tracking_free_track(track);
} }
BLI_freelistN(&tracking->tracks); BLI_freelistN(tracks);
}
if(tracking->reconstruction.cameras) static void tracking_reconstruction_free(MovieTrackingReconstruction *reconstruction)
MEM_freeN(tracking->reconstruction.cameras); {
if(reconstruction->cameras)
MEM_freeN(reconstruction->cameras);
}
static void tracking_object_free(MovieTrackingObject *object)
{
tracking_tracks_free(&object->tracks);
tracking_reconstruction_free(&object->reconstruction);
}
static void tracking_objects_free(ListBase *objects)
{
MovieTrackingObject *object;
for(object= objects->first; object; object= object->next)
tracking_object_free(object);
BLI_freelistN(objects);
}
void BKE_tracking_free(MovieTracking *tracking)
{
tracking_tracks_free(&tracking->tracks);
tracking_reconstruction_free(&tracking->reconstruction);
tracking_objects_free(&tracking->objects);
if(tracking->stabilization.scaleibuf) if(tracking->stabilization.scaleibuf)
IMB_freeImBuf(tracking->stabilization.scaleibuf); IMB_freeImBuf(tracking->stabilization.scaleibuf);
@ -547,6 +577,9 @@ void BKE_tracking_free(MovieTracking *tracking)
/*********************** tracks map *************************/ /*********************** tracks map *************************/
typedef struct TracksMap { typedef struct TracksMap {
char object_name[32];
int is_camera;
int num_tracks; int num_tracks;
int customdata_size; int customdata_size;
@ -558,10 +591,13 @@ typedef struct TracksMap {
int ptr; int ptr;
} TracksMap; } TracksMap;
static TracksMap *tracks_map_new(int num_tracks, int customdata_size) static TracksMap *tracks_map_new(const char *object_name, int is_camera, int num_tracks, int customdata_size)
{ {
TracksMap *map= MEM_callocN(sizeof(TracksMap), "TrackingsMap"); TracksMap *map= MEM_callocN(sizeof(TracksMap), "TrackingsMap");
strcpy(map->object_name, object_name);
map->is_camera= is_camera;
map->num_tracks= num_tracks; map->num_tracks= num_tracks;
map->customdata_size= customdata_size; map->customdata_size= customdata_size;
@ -607,10 +643,24 @@ static void tracks_map_insert(TracksMap *map, MovieTrackingTrack *track, void *c
static void tracks_map_merge(TracksMap *map, MovieTracking *tracking) static void tracks_map_merge(TracksMap *map, MovieTracking *tracking)
{ {
MovieTrackingTrack *track; MovieTrackingTrack *track;
MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking);
ListBase tracks= {NULL, NULL}, new_tracks= {NULL, NULL}; ListBase tracks= {NULL, NULL}, new_tracks= {NULL, NULL};
ListBase *old_tracks= &tracking->tracks; ListBase *old_tracks;
int a; int a;
if(map->is_camera) {
old_tracks= &tracking->tracks;
} else {
MovieTrackingObject *object= BKE_tracking_named_object(tracking, map->object_name);
if(!object) {
/* object was deleted by user, create new one */
object= BKE_tracking_new_object(tracking, map->object_name);
}
old_tracks= &object->tracks;
}
/* duplicate currently operating tracks to temporary list. /* duplicate currently operating tracks to temporary list.
this is needed to keep names in unique state and it's faster to change names this is needed to keep names in unique state and it's faster to change names
of currently operating tracks (if needed) */ of currently operating tracks (if needed) */
@ -634,7 +684,7 @@ static void tracks_map_merge(TracksMap *map, MovieTracking *tracking)
/* original track was found, re-use flags and remove this track */ /* original track was found, re-use flags and remove this track */
if(cur) { if(cur) {
if(cur==tracking->act_track) if(act_track)
replace_sel= 1; replace_sel= 1;
track->flag= cur->flag; track->flag= cur->flag;
@ -685,7 +735,7 @@ static void tracks_map_merge(TracksMap *map, MovieTracking *tracking)
track= next; track= next;
} }
tracking->tracks= new_tracks; *old_tracks= new_tracks;
} }
static void tracks_map_free(TracksMap *map, void (*customdata_free) (void *customdata)) static void tracks_map_free(TracksMap *map, void (*customdata_free) (void *customdata))
@ -737,27 +787,28 @@ typedef struct MovieTrackingContext {
MovieTrackingSettings settings; MovieTrackingSettings settings;
TracksMap *tracks_map; TracksMap *tracks_map;
short backwards, disable_failed, sequence; short backwards, sequence;
int sync_frame; int sync_frame;
} MovieTrackingContext; } MovieTrackingContext;
MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *user, short backwards, short disable_failed, short sequence) MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *user, short backwards, short sequence)
{ {
MovieTrackingContext *context= MEM_callocN(sizeof(MovieTrackingContext), "trackingContext"); MovieTrackingContext *context= MEM_callocN(sizeof(MovieTrackingContext), "trackingContext");
MovieTracking *tracking= &clip->tracking; MovieTracking *tracking= &clip->tracking;
MovieTrackingSettings *settings= &tracking->settings; MovieTrackingSettings *settings= &tracking->settings;
ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
MovieTrackingTrack *track; MovieTrackingTrack *track;
MovieTrackingObject *object= BKE_tracking_active_object(tracking);
int num_tracks= 0; int num_tracks= 0;
context->settings= *settings; context->settings= *settings;
context->backwards= backwards; context->backwards= backwards;
context->disable_failed= disable_failed;
context->sync_frame= user->framenr; context->sync_frame= user->framenr;
context->first_time= 1; context->first_time= 1;
context->sequence= sequence; context->sequence= sequence;
/* count */ /* count */
track= tracking->tracks.first; track= tracksbase->first;
while(track) { while(track) {
if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) { if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) {
MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr); MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
@ -772,12 +823,13 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u
if(num_tracks) { if(num_tracks) {
int width, height; int width, height;
context->tracks_map= tracks_map_new(num_tracks, sizeof(TrackContext)); context->tracks_map= tracks_map_new(object->name, object->flag & TRACKING_OBJECT_CAMERA,
num_tracks, sizeof(TrackContext));
BKE_movieclip_get_size(clip, user, &width, &height); BKE_movieclip_get_size(clip, user, &width, &height);
/* create tracking data */ /* create tracking data */
track= tracking->tracks.first; track= tracksbase->first;
while(track) { while(track) {
if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) { if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) {
MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr); MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
@ -883,29 +935,53 @@ void BKE_tracking_context_free(MovieTrackingContext *context)
MEM_freeN(context); MEM_freeN(context);
} }
static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track) /* zap channels from the imbuf that are disabled by the user. this can lead to
* better tracks sometimes. however, instead of simply zeroing the channels
* out, do a partial grayscale conversion so the display is better. */
static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int grayscale)
{ {
int x, y; int x, y;
float scale;
if((track->flag&(TRACK_DISABLE_RED|TRACK_DISABLE_GREEN|TRACK_DISABLE_BLUE))==0) if((track->flag&(TRACK_DISABLE_RED|TRACK_DISABLE_GREEN|TRACK_DISABLE_BLUE))==0 && !grayscale)
return; return;
/* If only some components are selected, it's important to rescale the result
* appropriately so that e.g. if only blue is selected, it's not zeroed out. */
scale = ((track->flag&TRACK_DISABLE_RED ) ? 0.0f : 0.2126f) +
((track->flag&TRACK_DISABLE_GREEN) ? 0.0f : 0.7152f) +
((track->flag&TRACK_DISABLE_BLUE) ? 0.0f : 0.0722f);
for(y= 0; y<ibuf->y; y++) { for(y= 0; y<ibuf->y; y++) {
for (x= 0; x<ibuf->x; x++) { for (x= 0; x<ibuf->x; x++) {
int pixel= ibuf->x*y + x; int pixel= ibuf->x*y + x;
if(ibuf->rect_float) { if(ibuf->rect_float) {
float *rrgbf= ibuf->rect_float + pixel*4; float *rrgbf= ibuf->rect_float + pixel*4;
float r = (track->flag&TRACK_DISABLE_RED) ? 0.0f : rrgbf[0];
if(track->flag&TRACK_DISABLE_RED) rrgbf[0]= 0; float g = (track->flag&TRACK_DISABLE_GREEN) ? 0.0f : rrgbf[1];
if(track->flag&TRACK_DISABLE_GREEN) rrgbf[1]= 0; float b = (track->flag&TRACK_DISABLE_BLUE) ? 0.0f : rrgbf[2];
if(track->flag&TRACK_DISABLE_BLUE) rrgbf[2]= 0; if (grayscale) {
float gray = (0.2126f*r + 0.7152f*g + 0.0722f*b) / scale;
rrgbf[0] = rrgbf[1] = rrgbf[2] = gray;
} else {
rrgbf[0] = r;
rrgbf[1] = g;
rrgbf[2] = b;
}
} else { } else {
char *rrgb= (char*)ibuf->rect + pixel*4; char *rrgb= (char*)ibuf->rect + pixel*4;
char r = (track->flag&TRACK_DISABLE_RED) ? 0 : rrgb[0];
if(track->flag&TRACK_DISABLE_RED) rrgb[0]= 0; char g = (track->flag&TRACK_DISABLE_GREEN) ? 0 : rrgb[1];
if(track->flag&TRACK_DISABLE_GREEN) rrgb[1]= 0; char b = (track->flag&TRACK_DISABLE_BLUE) ? 0 : rrgb[2];
if(track->flag&TRACK_DISABLE_BLUE) rrgb[2]= 0; if (grayscale) {
float gray = (0.2126f*r + 0.7152f*g + 0.0722f*b) / scale;
rrgb[0] = rrgb[1] = rrgb[2] = gray;
} else {
rrgb[0] = r;
rrgb[1] = g;
rrgb[2] = b;
}
} }
} }
} }
@ -947,7 +1023,12 @@ static ImBuf *get_area_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTracki
origin[1]= y1-margin; origin[1]= y1-margin;
} }
disable_imbuf_channels(tmpibuf, track); if ((track->flag & TRACK_PREVIEW_GRAYSCALE) ||
(track->flag & TRACK_DISABLE_RED) ||
(track->flag & TRACK_DISABLE_GREEN) ||
(track->flag & TRACK_DISABLE_BLUE) ) {
disable_imbuf_channels(tmpibuf, track, 1 /* grayscale */);
}
return tmpibuf; return tmpibuf;
} }
@ -976,7 +1057,7 @@ static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieT
height= (track->search_max[1]-track->search_min[1])*ibuf->y; height= (track->search_max[1]-track->search_min[1])*ibuf->y;
tmpibuf= BKE_tracking_get_search_imbuf(ibuf, track, marker, 0, 0, pos, origin); tmpibuf= BKE_tracking_get_search_imbuf(ibuf, track, marker, 0, 0, pos, origin);
disable_imbuf_channels(tmpibuf, track); disable_imbuf_channels(tmpibuf, track, 0 /* don't grayscale */);
*width_r= width; *width_r= width;
*height_r= height; *height_r= height;
@ -988,14 +1069,11 @@ static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieT
if(tmpibuf->rect_float) { if(tmpibuf->rect_float) {
float *rrgbf= tmpibuf->rect_float + pixel*4; float *rrgbf= tmpibuf->rect_float + pixel*4;
*fp= 0.2126*rrgbf[0] + 0.7152*rrgbf[1] + 0.0722*rrgbf[2]; *fp= 0.2126*rrgbf[0] + 0.7152*rrgbf[1] + 0.0722*rrgbf[2];
} else { } else {
unsigned char *rrgb= (unsigned char*)tmpibuf->rect + pixel*4; unsigned char *rrgb= (unsigned char*)tmpibuf->rect + pixel*4;
*fp= (0.2126*rrgb[0] + 0.7152*rrgb[1] + 0.0722*rrgb[2])/255.0f; *fp= (0.2126*rrgb[0] + 0.7152*rrgb[1] + 0.0722*rrgb[2])/255.0f;
} }
fp++; fp++;
} }
} }
@ -1017,14 +1095,11 @@ static unsigned char *get_ucharbuf(ImBuf *ibuf)
if(ibuf->rect_float) { if(ibuf->rect_float) {
float *rrgbf= ibuf->rect_float + pixel*4; float *rrgbf= ibuf->rect_float + pixel*4;
*cp= FTOCHAR(0.2126f*rrgbf[0] + 0.7152f*rrgbf[1] + 0.0722f*rrgbf[2]); *cp= FTOCHAR(0.2126f*rrgbf[0] + 0.7152f*rrgbf[1] + 0.0722f*rrgbf[2]);
} else { } else {
unsigned char *rrgb= (unsigned char*)ibuf->rect + pixel*4; unsigned char *rrgb= (unsigned char*)ibuf->rect + pixel*4;
*cp= 0.2126f*rrgb[0] + 0.7152f*rrgb[1] + 0.0722f*rrgb[2]; *cp= 0.2126f*rrgb[0] + 0.7152f*rrgb[1] + 0.0722f*rrgb[2];
} }
cp++; cp++;
} }
} }
@ -1039,7 +1114,7 @@ static unsigned char *get_search_bytebuf(ImBuf *ibuf, MovieTrackingTrack *track,
unsigned char *pixels; unsigned char *pixels;
tmpibuf= BKE_tracking_get_search_imbuf(ibuf, track, marker, 0, 0, pos, origin); tmpibuf= BKE_tracking_get_search_imbuf(ibuf, track, marker, 0, 0, pos, origin);
disable_imbuf_channels(tmpibuf, track); disable_imbuf_channels(tmpibuf, track, 0 /* don't grayscale */);
*width_r= tmpibuf->x; *width_r= tmpibuf->x;
*height_r= tmpibuf->y; *height_r= tmpibuf->y;
@ -1183,8 +1258,7 @@ int BKE_tracking_next(MovieTrackingContext *context)
double x1, y1, x2, y2; double x1, y1, x2, y2;
ImBuf *ibuf= NULL; ImBuf *ibuf= NULL;
MovieTrackingMarker marker_new, *marker_keyed; MovieTrackingMarker marker_new, *marker_keyed;
int onbound= 0, coords_correct= 0; int onbound= 0, nextfra;
int nextfra;
if(track->pattern_match==TRACK_MATCH_KEYFRAME) if(track->pattern_match==TRACK_MATCH_KEYFRAME)
need_readjust= context->first_time; need_readjust= context->first_time;
@ -1302,8 +1376,7 @@ int BKE_tracking_next(MovieTrackingContext *context)
MEM_freeN(image_new); MEM_freeN(image_new);
} }
coords_correct= !onbound && !isnan(x2) && !isnan(y2) && finite(x2) && finite(y2); if(tracked && !onbound && finite(x2) && finite(y2)) {
if(coords_correct && (tracked || !context->disable_failed)) {
if(context->first_time) { if(context->first_time) {
#pragma omp critical #pragma omp critical
{ {
@ -1370,6 +1443,8 @@ typedef struct MovieReconstructContext {
struct libmv_Reconstruction *reconstruction; struct libmv_Reconstruction *reconstruction;
#endif #endif
char object_name[32];
int is_camera;
float focal_length; float focal_length;
float principal_point[2]; float principal_point[2];
@ -1391,13 +1466,13 @@ typedef struct ReconstructProgressData {
} ReconstructProgressData; } ReconstructProgressData;
#if WITH_LIBMV #if WITH_LIBMV
static struct libmv_Tracks *create_libmv_tracks(MovieTracking *tracking, int width, int height) static struct libmv_Tracks *create_libmv_tracks(ListBase *tracksbase, int width, int height)
{ {
int tracknr= 0; int tracknr= 0;
MovieTrackingTrack *track; MovieTrackingTrack *track;
struct libmv_Tracks *tracks= libmv_tracksNew(); struct libmv_Tracks *tracks= libmv_tracksNew();
track= tracking->tracks.first; track= tracksbase->first;
while(track) { while(track) {
int a= 0; int a= 0;
@ -1441,16 +1516,28 @@ static void retrieve_libmv_reconstruct_intrinscis(MovieReconstructContext *conte
static int retrieve_libmv_reconstruct_tracks(MovieReconstructContext *context, MovieTracking *tracking) static int retrieve_libmv_reconstruct_tracks(MovieReconstructContext *context, MovieTracking *tracking)
{ {
struct libmv_Reconstruction *libmv_reconstruction= context->reconstruction; struct libmv_Reconstruction *libmv_reconstruction= context->reconstruction;
MovieTrackingReconstruction *reconstruction= &tracking->reconstruction; MovieTrackingReconstruction *reconstruction= NULL;
MovieReconstructedCamera *reconstructed; MovieReconstructedCamera *reconstructed;
MovieTrackingTrack *track; MovieTrackingTrack *track;
ListBase *tracksbase= NULL;
int ok= 1, tracknr= 0, a, origin_set= 0; int ok= 1, tracknr= 0, a, origin_set= 0;
int sfra= context->sfra, efra= context->efra; int sfra= context->sfra, efra= context->efra;
float imat[4][4]; float imat[4][4];
if(context->is_camera) {
tracksbase= &tracking->tracks;
reconstruction= &tracking->reconstruction;
}
else {
MovieTrackingObject *object= BKE_tracking_named_object(tracking, context->object_name);
tracksbase= &object->tracks;
reconstruction= &object->reconstruction;
}
unit_m4(imat); unit_m4(imat);
track= tracking->tracks.first; track= tracksbase->first;
while(track) { while(track) {
double pos[3]; double pos[3];
@ -1516,7 +1603,7 @@ static int retrieve_libmv_reconstruct_tracks(MovieReconstructContext *context, M
} }
if(origin_set) { if(origin_set) {
track= tracking->tracks.first; track= tracksbase->first;
while(track) { while(track) {
if(track->flag&TRACK_HAS_BUNDLE) if(track->flag&TRACK_HAS_BUNDLE)
mul_v3_m4v3(track->bundle_pos, imat, track->bundle_pos); mul_v3_m4v3(track->bundle_pos, imat, track->bundle_pos);
@ -1532,19 +1619,20 @@ static int retrieve_libmv_reconstruct_tracks(MovieReconstructContext *context, M
static int retrieve_libmv_reconstruct(MovieReconstructContext *context, MovieTracking *tracking) static int retrieve_libmv_reconstruct(MovieReconstructContext *context, MovieTracking *tracking)
{ {
tracks_map_merge(context->tracks_map, tracking);
/* take the intrinscis back from libmv */ /* take the intrinscis back from libmv */
retrieve_libmv_reconstruct_intrinscis(context, tracking); retrieve_libmv_reconstruct_intrinscis(context, tracking);
return retrieve_libmv_reconstruct_tracks(context, tracking); return retrieve_libmv_reconstruct_tracks(context, tracking);
} }
static int get_refine_intrinsics_flags(MovieTracking *tracking) static int get_refine_intrinsics_flags(MovieTracking *tracking, MovieTrackingObject *object)
{ {
int refine= tracking->settings.refine_camera_intrinsics; int refine= tracking->settings.refine_camera_intrinsics;
int flags= 0; int flags= 0;
if((object->flag&TRACKING_OBJECT_CAMERA)==0)
return 0;
if(refine&REFINE_FOCAL_LENGTH) if(refine&REFINE_FOCAL_LENGTH)
flags|= LIBMV_REFINE_FOCAL_LENGTH; flags|= LIBMV_REFINE_FOCAL_LENGTH;
@ -1560,13 +1648,13 @@ static int get_refine_intrinsics_flags(MovieTracking *tracking)
return flags; return flags;
} }
static int count_tracks_on_both_keyframes(MovieTracking *tracking) static int count_tracks_on_both_keyframes(MovieTracking *tracking, ListBase *tracksbase)
{ {
int tot= 0; int tot= 0;
int frame1= tracking->settings.keyframe1, frame2= tracking->settings.keyframe2; int frame1= tracking->settings.keyframe1, frame2= tracking->settings.keyframe2;
MovieTrackingTrack *track; MovieTrackingTrack *track;
track= tracking->tracks.first; track= tracksbase->first;
while(track) { while(track) {
if(BKE_tracking_has_marker(track, frame1)) if(BKE_tracking_has_marker(track, frame1))
if(BKE_tracking_has_marker(track, frame2)) if(BKE_tracking_has_marker(track, frame2))
@ -1579,10 +1667,12 @@ static int count_tracks_on_both_keyframes(MovieTracking *tracking)
} }
#endif #endif
int BKE_tracking_can_reconstruct(MovieTracking *tracking, char *error_msg, int error_size) int BKE_tracking_can_reconstruct(MovieTracking *tracking, MovieTrackingObject *object, char *error_msg, int error_size)
{ {
#if WITH_LIBMV #if WITH_LIBMV
if(count_tracks_on_both_keyframes(tracking)<8) { ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object);
if(count_tracks_on_both_keyframes(tracking, tracksbase)<8) {
BLI_strncpy(error_msg, "At least 8 tracks on both of keyframes are needed for reconstruction", error_size); BLI_strncpy(error_msg, "At least 8 tracks on both of keyframes are needed for reconstruction", error_size);
return 0; return 0;
} }
@ -1590,31 +1680,37 @@ int BKE_tracking_can_reconstruct(MovieTracking *tracking, char *error_msg, int e
return 1; return 1;
#else #else
BLI_strncpy(error_msg, "Blender is compiled without motion tracking library", error_size); BLI_strncpy(error_msg, "Blender is compiled without motion tracking library", error_size);
(void) tracking; (void)tracking;
(void)object;
return 0; return 0;
#endif #endif
} }
MovieReconstructContext* BKE_tracking_reconstruction_context_new(MovieTracking *tracking, MovieReconstructContext* BKE_tracking_reconstruction_context_new(MovieTracking *tracking,
int keyframe1, int keyframe2, int width, int height) MovieTrackingObject *object, int keyframe1, int keyframe2, int width, int height)
{ {
MovieReconstructContext *context= MEM_callocN(sizeof(MovieReconstructContext), "MovieReconstructContext data"); MovieReconstructContext *context= MEM_callocN(sizeof(MovieReconstructContext), "MovieReconstructContext data");
MovieTrackingCamera *camera= &tracking->camera; MovieTrackingCamera *camera= &tracking->camera;
ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object);
float aspy= 1.0f/tracking->camera.pixel_aspect; float aspy= 1.0f/tracking->camera.pixel_aspect;
int num_tracks= BLI_countlist(&tracking->tracks); int num_tracks= BLI_countlist(tracksbase);
int sfra= INT_MAX, efra= INT_MIN; int sfra= INT_MAX, efra= INT_MIN;
MovieTrackingTrack *track; MovieTrackingTrack *track;
context->tracks_map= tracks_map_new(num_tracks, 0); strcpy(context->object_name, object->name);
track= tracking->tracks.first; context->is_camera = object->flag&TRACKING_OBJECT_CAMERA;
context->tracks_map= tracks_map_new(context->object_name, context->is_camera, num_tracks, 0);
track= tracksbase->first;
while(track) { while(track) {
int first= 0, last= track->markersnr; int first= 0, last= track->markersnr-1;
MovieTrackingMarker *first_marker= &track->markers[0]; MovieTrackingMarker *first_marker= &track->markers[0];
MovieTrackingMarker *last_marker= &track->markers[track->markersnr-1]; MovieTrackingMarker *last_marker= &track->markers[track->markersnr-1];
/* find first not-disabled marker */ /* find first not-disabled marker */
while(first<track->markersnr-1 && first_marker->flag&MARKER_DISABLED) { while(first<=track->markersnr-1 && first_marker->flag&MARKER_DISABLED) {
first++; first++;
first_marker++; first_marker++;
} }
@ -1640,10 +1736,10 @@ MovieReconstructContext* BKE_tracking_reconstruction_context_new(MovieTracking *
context->efra= efra; context->efra= efra;
#ifdef WITH_LIBMV #ifdef WITH_LIBMV
context->tracks= create_libmv_tracks(tracking, width, height*aspy); context->tracks= create_libmv_tracks(tracksbase, width, height*aspy);
context->keyframe1= keyframe1; context->keyframe1= keyframe1;
context->keyframe2= keyframe2; context->keyframe2= keyframe2;
context->refine_flags= get_refine_intrinsics_flags(tracking); context->refine_flags= get_refine_intrinsics_flags(tracking, object);
#else #else
(void) width; (void) width;
(void) height; (void) height;
@ -1740,8 +1836,22 @@ void BKE_tracking_solve_reconstruction(MovieReconstructContext *context, short *
int BKE_tracking_finish_reconstruction(MovieReconstructContext *context, MovieTracking *tracking) int BKE_tracking_finish_reconstruction(MovieReconstructContext *context, MovieTracking *tracking)
{ {
tracking->reconstruction.error= context->reprojection_error; MovieTrackingReconstruction *reconstruction;
tracking->reconstruction.flag|= TRACKING_RECONSTRUCTED;
tracks_map_merge(context->tracks_map, tracking);
if(context->is_camera) {
reconstruction= &tracking->reconstruction;
}
else {
MovieTrackingObject *object;
object= BKE_tracking_named_object(tracking, context->object_name);
reconstruction= &object->reconstruction;
}
reconstruction->error= context->reprojection_error;
reconstruction->flag|= TRACKING_RECONSTRUCTED;
#ifdef WITH_LIBMV #ifdef WITH_LIBMV
if(!retrieve_libmv_reconstruct(context, tracking)) if(!retrieve_libmv_reconstruct(context, tracking))
@ -1751,14 +1861,15 @@ int BKE_tracking_finish_reconstruction(MovieReconstructContext *context, MovieTr
return 1; return 1;
} }
void BKE_track_unique_name(MovieTracking *tracking, MovieTrackingTrack *track) void BKE_track_unique_name(ListBase *tracksbase, MovieTrackingTrack *track)
{ {
BLI_uniquename(&tracking->tracks, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name)); BLI_uniquename(tracksbase, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
} }
MovieTrackingTrack *BKE_tracking_named_track(MovieTracking *tracking, const char *name) MovieTrackingTrack *BKE_tracking_named_track(MovieTracking *tracking, MovieTrackingObject *object, const char *name)
{ {
MovieTrackingTrack *track= tracking->tracks.first; ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object);
MovieTrackingTrack *track= tracksbase->first;
while(track) { while(track) {
if(!strcmp(track->name, name)) if(!strcmp(track->name, name))
@ -1770,9 +1881,8 @@ MovieTrackingTrack *BKE_tracking_named_track(MovieTracking *tracking, const char
return NULL; return NULL;
} }
static int reconstruction_camera_index(MovieTracking *tracking, int framenr, int nearest) static int reconstruction_camera_index(MovieTrackingReconstruction *reconstruction, int framenr, int nearest)
{ {
MovieTrackingReconstruction *reconstruction= &tracking->reconstruction;
MovieReconstructedCamera *cameras= reconstruction->cameras; MovieReconstructedCamera *cameras= reconstruction->cameras;
int a= 0, d= 1; int a= 0, d= 1;
@ -1824,21 +1934,41 @@ static int reconstruction_camera_index(MovieTracking *tracking, int framenr, int
return -1; return -1;
} }
MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(MovieTracking *tracking, int framenr) static void scale_reconstructed_camera(MovieTrackingObject *object, float mat[4][4])
{ {
int a= reconstruction_camera_index(tracking, framenr, 0); if((object->flag&TRACKING_OBJECT_CAMERA)==0) {
float smat[4][4];
scale_m4_fl(smat, 1.0f/object->scale);
mult_m4_m4m4(mat, mat, smat);
}
}
MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(MovieTracking *tracking,
MovieTrackingObject *object, int framenr)
{
MovieTrackingReconstruction *reconstruction;
int a;
reconstruction= BKE_tracking_object_reconstruction(tracking, object);
a= reconstruction_camera_index(reconstruction, framenr, 0);
if(a==-1) if(a==-1)
return NULL; return NULL;
return &tracking->reconstruction.cameras[a]; return &reconstruction->cameras[a];
} }
void BKE_tracking_get_interpolated_camera(MovieTracking *tracking, int framenr, float mat[4][4]) void BKE_tracking_get_interpolated_camera(MovieTracking *tracking, MovieTrackingObject *object,
int framenr, float mat[4][4])
{ {
MovieTrackingReconstruction *reconstruction= &tracking->reconstruction; MovieTrackingReconstruction *reconstruction;
MovieReconstructedCamera *cameras= reconstruction->cameras; MovieReconstructedCamera *cameras;
int a= reconstruction_camera_index(tracking, framenr, 1); int a;
reconstruction= BKE_tracking_object_reconstruction(tracking, object);
cameras= reconstruction->cameras;
a= reconstruction_camera_index(reconstruction, framenr, 1);
if(a==-1) { if(a==-1) {
unit_m4(mat); unit_m4(mat);
@ -1852,6 +1982,8 @@ void BKE_tracking_get_interpolated_camera(MovieTracking *tracking, int framenr,
} else { } else {
copy_m4_m4(mat, cameras[a].mat); copy_m4_m4(mat, cameras[a].mat);
} }
scale_reconstructed_camera(object, mat);
} }
void BKE_get_tracking_mat(Scene *scene, Object *ob, float mat[4][4]) void BKE_get_tracking_mat(Scene *scene, Object *ob, float mat[4][4])
@ -1890,7 +2022,8 @@ void BKE_tracking_camera_to_blender(MovieTracking *tracking, Scene *scene, Camer
BKE_tracking_camera_shift(tracking, width, height, &camera->shiftx, &camera->shifty); BKE_tracking_camera_shift(tracking, width, height, &camera->shiftx, &camera->shifty);
} }
void BKE_tracking_projection_matrix(MovieTracking *tracking, int framenr, int winx, int winy, float mat[4][4]) void BKE_tracking_projection_matrix(MovieTracking *tracking, MovieTrackingObject *object,
int framenr, int winx, int winy, float mat[4][4])
{ {
MovieReconstructedCamera *camera; MovieReconstructedCamera *camera;
float lens= tracking->camera.focal*tracking->camera.sensor_width/(float)winx; float lens= tracking->camera.focal*tracking->camera.sensor_width/(float)winx;
@ -1923,7 +2056,8 @@ void BKE_tracking_projection_matrix(MovieTracking *tracking, int framenr, int wi
perspective_m4(winmat, left, right, bottom, top, clipsta, clipend); perspective_m4(winmat, left, right, bottom, top, clipsta, clipend);
camera= BKE_tracking_get_reconstructed_camera(tracking, framenr); camera= BKE_tracking_get_reconstructed_camera(tracking, object, framenr);
if(camera) { if(camera) {
float imat[4][4]; float imat[4][4];
@ -1932,6 +2066,77 @@ void BKE_tracking_projection_matrix(MovieTracking *tracking, int framenr, int wi
} else copy_m4_m4(mat, winmat); } else copy_m4_m4(mat, winmat);
} }
ListBase *BKE_tracking_get_tracks(MovieTracking *tracking)
{
MovieTrackingObject *object= BKE_tracking_active_object(tracking);
if(object && (object->flag & TRACKING_OBJECT_CAMERA) == 0) {
return &object->tracks;
}
return &tracking->tracks;
}
MovieTrackingTrack *BKE_tracking_active_track(MovieTracking *tracking)
{
ListBase *tracksbase;
if(!tracking->act_track)
return NULL;
tracksbase= BKE_tracking_get_tracks(tracking);
/* check that active track is in current tracks list */
if(BLI_findindex(tracksbase, tracking->act_track) >= 0)
return tracking->act_track;
return NULL;
}
MovieTrackingObject *BKE_tracking_active_object(MovieTracking *tracking)
{
return BLI_findlink(&tracking->objects, tracking->objectnr);
}
MovieTrackingObject *BKE_tracking_get_camera_object(MovieTracking *tracking)
{
MovieTrackingObject *object= tracking->objects.first;
while(object) {
if(object->flag & TRACKING_OBJECT_CAMERA)
return object;
object= object->next;
}
return NULL;
}
ListBase *BKE_tracking_object_tracks(MovieTracking *tracking, MovieTrackingObject *object)
{
if(object->flag & TRACKING_OBJECT_CAMERA) {
return &tracking->tracks;
}
return &object->tracks;
}
MovieTrackingReconstruction *BKE_tracking_object_reconstruction(MovieTracking *tracking, MovieTrackingObject *object)
{
if(object->flag & TRACKING_OBJECT_CAMERA) {
return &tracking->reconstruction;
}
return &object->reconstruction;
}
MovieTrackingReconstruction *BKE_tracking_get_reconstruction(MovieTracking *tracking)
{
MovieTrackingObject *object= BKE_tracking_active_object(tracking);
return BKE_tracking_object_reconstruction(tracking, object);
}
void BKE_tracking_apply_intrinsics(MovieTracking *tracking, float co[2], float nco[2]) void BKE_tracking_apply_intrinsics(MovieTracking *tracking, float co[2], float nco[2])
{ {
MovieTrackingCamera *camera= &tracking->camera; MovieTrackingCamera *camera= &tracking->camera;
@ -2018,8 +2223,9 @@ static int point_in_layer(bGPDlayer *layer, float x, float y)
return 0; return 0;
} }
static void retrieve_libmv_features(MovieTracking *tracking, struct libmv_Features *features, static void retrieve_libmv_features(MovieTracking *tracking, ListBase *tracksbase,
int framenr, int width, int height, bGPDlayer *layer, int place_outside_layer) struct libmv_Features *features, int framenr, int width, int height,
bGPDlayer *layer, int place_outside_layer)
{ {
int a; int a;
@ -2039,7 +2245,7 @@ static void retrieve_libmv_features(MovieTracking *tracking, struct libmv_Featur
ok= point_in_layer(layer, xu, yu)!=place_outside_layer; ok= point_in_layer(layer, xu, yu)!=place_outside_layer;
if(ok) { if(ok) {
track= BKE_tracking_add_track(tracking, xu, yu, framenr, width, height); track= BKE_tracking_add_track(tracking, tracksbase, xu, yu, framenr, width, height);
track->flag|= SELECT; track->flag|= SELECT;
track->pat_flag|= SELECT; track->pat_flag|= SELECT;
track->search_flag|= SELECT; track->search_flag|= SELECT;
@ -2048,7 +2254,7 @@ static void retrieve_libmv_features(MovieTracking *tracking, struct libmv_Featur
} }
#endif #endif
void BKE_tracking_detect_fast(MovieTracking *tracking, ImBuf *ibuf, void BKE_tracking_detect_fast(MovieTracking *tracking, ListBase *tracksbase, ImBuf *ibuf,
int framenr, int margin, int min_trackness, int min_distance, bGPDlayer *layer, int framenr, int margin, int min_trackness, int min_distance, bGPDlayer *layer,
int place_outside_layer) int place_outside_layer)
{ {
@ -2056,15 +2262,18 @@ void BKE_tracking_detect_fast(MovieTracking *tracking, ImBuf *ibuf,
struct libmv_Features *features; struct libmv_Features *features;
unsigned char *pixels= get_ucharbuf(ibuf); unsigned char *pixels= get_ucharbuf(ibuf);
features= libmv_detectFeaturesFAST(pixels, ibuf->x, ibuf->y, ibuf->x, margin, min_trackness, min_distance); features= libmv_detectFeaturesFAST(pixels, ibuf->x, ibuf->y, ibuf->x,
margin, min_trackness, min_distance);
MEM_freeN(pixels); MEM_freeN(pixels);
retrieve_libmv_features(tracking, features, framenr, ibuf->x, ibuf->y, layer, place_outside_layer); retrieve_libmv_features(tracking, tracksbase, features, framenr,
ibuf->x, ibuf->y, layer, place_outside_layer);
libmv_destroyFeatures(features); libmv_destroyFeatures(features);
#else #else
(void)tracking; (void)tracking;
(void)tracksbase;
(void)ibuf; (void)ibuf;
(void)framenr; (void)framenr;
(void)margin; (void)margin;
@ -2075,22 +2284,34 @@ void BKE_tracking_detect_fast(MovieTracking *tracking, ImBuf *ibuf,
#endif #endif
} }
MovieTrackingTrack *BKE_tracking_indexed_track(MovieTracking *tracking, int tracknr) MovieTrackingTrack *BKE_tracking_indexed_track(MovieTracking *tracking, int tracknr, ListBase **tracksbase_r)
{ {
MovieTrackingTrack *track= tracking->tracks.first; MovieTrackingObject *object;
int cur= 1; int cur= 1;
while(track) { object= tracking->objects.first;
if(track->flag&TRACK_HAS_BUNDLE) { while(object) {
if(cur==tracknr) ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object);
return track; MovieTrackingTrack *track= tracksbase->first;
cur++; while(track) {
if(track->flag&TRACK_HAS_BUNDLE) {
if(cur==tracknr) {
*tracksbase_r= tracksbase;
return track;
}
cur++;
}
track= track->next;
} }
track= track->next; object= object->next;
} }
*tracksbase_r= NULL;
return NULL; return NULL;
} }
@ -2102,6 +2323,8 @@ static int stabilization_median_point(MovieTracking *tracking, int framenr, floa
INIT_MINMAX2(min, max); INIT_MINMAX2(min, max);
(void) tracking;
track= tracking->tracks.first; track= tracking->tracks.first;
while(track) { while(track) {
if(track->flag&TRACK_USE_2D_STAB) { if(track->flag&TRACK_USE_2D_STAB) {
@ -2539,12 +2762,12 @@ ImBuf *BKE_tracking_distort(MovieTracking *tracking, ImBuf *ibuf, int width, int
} }
/* area - which part of marker should be selected. see TRACK_AREA_* constants */ /* area - which part of marker should be selected. see TRACK_AREA_* constants */
void BKE_tracking_select_track(MovieTracking *tracking, MovieTrackingTrack *track, int area, int extend) void BKE_tracking_select_track(ListBase *tracksbase, MovieTrackingTrack *track, int area, int extend)
{ {
if(extend) { if(extend) {
BKE_tracking_track_flag(track, area, SELECT, 0); BKE_tracking_track_flag(track, area, SELECT, 0);
} else { } else {
MovieTrackingTrack *cur= tracking->tracks.first; MovieTrackingTrack *cur= tracksbase->first;
while(cur) { while(cur) {
if(cur==track) { if(cur==track) {
@ -2564,3 +2787,78 @@ void BKE_tracking_deselect_track(MovieTrackingTrack *track, int area)
{ {
BKE_tracking_track_flag(track, area, SELECT, 1); BKE_tracking_track_flag(track, area, SELECT, 1);
} }
MovieTrackingObject *BKE_tracking_new_object(MovieTracking *tracking, const char *name)
{
MovieTrackingObject *object= MEM_callocN(sizeof(MovieTrackingObject), "tracking object");
if(tracking->tot_object==0) {
/* first object is always camera */
BLI_strncpy(object->name, "Camera", sizeof(object->name));
object->flag|= TRACKING_OBJECT_CAMERA;
}
else {
BLI_strncpy(object->name, name, sizeof(object->name));
}
BLI_addtail(&tracking->objects, object);
tracking->tot_object++;
tracking->objectnr= BLI_countlist(&tracking->objects) - 1;
BKE_tracking_object_unique_name(tracking, object);
return object;
}
void BKE_tracking_remove_object(MovieTracking *tracking, MovieTrackingObject *object)
{
MovieTrackingTrack *track;
int index= BLI_findindex(&tracking->objects, object);
if(index<0)
return;
if(object->flag & TRACKING_OBJECT_CAMERA) {
/* object used for camera solving can't be deleted */
return;
}
track= object->tracks.first;
while(track) {
if(track==tracking->act_track)
tracking->act_track= NULL;
track= track->next;
}
tracking_object_free(object);
BLI_freelinkN(&tracking->objects, object);
tracking->tot_object--;
if(index>0)
tracking->objectnr= index-1;
else
tracking->objectnr= 0;
}
void BKE_tracking_object_unique_name(MovieTracking *tracking, MovieTrackingObject *object)
{
BLI_uniquename(&tracking->objects, object, "Object", '.', offsetof(MovieTrackingObject, name), sizeof(object->name));
}
MovieTrackingObject *BKE_tracking_named_object(MovieTracking *tracking, const char *name)
{
MovieTrackingObject *object= tracking->objects.first;
while(object) {
if(!strcmp(object->name, name))
return object;
object= object->next;
}
return NULL;
}

@ -0,0 +1,185 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Joseph Eagar.
*
* ***** END GPL LICENSE BLOCK *****
*/
/*
* this library needs to be changed to not use macros quite so heavily,
* and to be more of a complete array API. The way arrays are
* exposed to client code as normal C arrays is very useful though, imho.
* it does require some use of macros, however.
*
* anyway, it's used a bit too heavily to simply rewrite as a
* more "correct" solution without macros entirely. I originally wrote this
* to be very easy to use, without the normal pain of most array libraries.
* This was especially helpful when it came to the massive refactors necessary
* for bmesh, and really helped to speed the process up. - joeedh
*
* little array macro library. example of usage:
*
* int *arr = NULL;
* BLI_array_declare(arr);
* int i;
*
* for (i=0; i<10; i++) {
* BLI_array_growone(arr);
* arr[i] = something;
* }
* BLI_array_free(arr);
*
* arrays are buffered, using double-buffering (so on each reallocation,
* the array size is doubled). supposedly this should give good Big Oh
* behaviour, though it may not be the best in practice.
*/
#define BLI_array_declare(arr) \
int _##arr##_count = 0; \
void *_##arr##_tmp; \
void *_##arr##_static = NULL
/* this will use stack space, up to maxstatic array elements, before
* switching to dynamic heap allocation */
#define BLI_array_staticdeclare(arr, maxstatic) \
int _##arr##_count = 0; \
void *_##arr##_tmp; \
char _##arr##_static[maxstatic*sizeof(arr)]
/* this returns the entire size of the array, including any buffering. */
#define BLI_array_totalsize_dyn(arr) ( \
((arr)==NULL) ? \
0 : \
MEM_allocN_len(arr) / sizeof(*arr) \
)
#define BLI_array_totalsize(arr) ( \
(size_t) \
(((void *)(arr) == (void *)_##arr##_static && (void *)(arr) != NULL) ? \
(sizeof(_##arr##_static) / sizeof(*arr)) : \
BLI_array_totalsize_dyn(arr)) \
)
/* this returns the logical size of the array, not including buffering. */
#define BLI_array_count(arr) _##arr##_count
/* Grow the array by a fixed number of items. zeroes the new elements.
*
* Allow for a large 'num' value when the new size is more then double
* to allocate the exact sized array. */
#define _bli_array_grow_items(arr, num) ( \
(BLI_array_totalsize(arr) >= _##arr##_count + num) ? \
(_##arr##_count += num) : \
( \
(void) (_##arr##_tmp = MEM_callocN( \
sizeof(*arr) * (num < _##arr##_count ? \
(_##arr##_count * 2 + 2) : \
(_##arr##_count + num)), \
#arr " " __FILE__ ":" STRINGIFY(__LINE__) \
) \
), \
(void) (arr && memcpy(_##arr##_tmp, \
arr, \
sizeof(*arr) * _##arr##_count) \
), \
(void) (arr && ((void *)(arr) != (void*)_##arr##_static ? \
(MEM_freeN(arr), arr) : \
arr) \
), \
(void) (arr = _##arr##_tmp \
), \
(_##arr##_count += num) \
) \
)
/* grow an array by a specified number of items */
#define BLI_array_growitems(arr, num) ( \
((void *)(arr)==NULL && (void *)(_##arr##_static) != NULL) ? \
((arr= (void*)_##arr##_static), (_##arr##_count += num)) : \
_bli_array_grow_items(arr, num) \
)
/* returns length of array */
#define BLI_array_growone(arr) BLI_array_growitems(arr, 1)
/* appends an item to the array. */
#define BLI_array_append(arr, item) ( \
(void) BLI_array_growone(arr), \
(void) (arr[_##arr##_count - 1] = item) \
)
/* appends an item to the array and returns a pointer to the item in the array.
* item is not a pointer, but actual data value.*/
#define BLI_array_append_r(arr, item) ( \
(void) BLI_array_growone(arr), \
(void) (arr[_##arr##_count - 1] = item), \
(&arr[_##arr##_count - 1]) \
)
#define BLI_array_free(arr) \
if (arr && (char *)arr != _##arr##_static) { \
BLI_array_fake_user(arr); \
MEM_freeN(arr); \
}
#define BLI_array_pop(arr) ( \
(arr&&_##arr##_count) ? \
arr[--_##arr##_count] : \
0 \
)
/* resets the logical size of an array to zero, but doesn't
* free the memory. */
#define BLI_array_empty(arr) \
_##arr##_count=0
/* set the count of the array, doesn't actually increase the allocated array
* size. don't use this unless you know what you're doing. */
#define BLI_array_set_length(arr, count) \
_##arr##_count = (count)
/* only to prevent unused warnings */
#define BLI_array_fake_user(arr) \
(void)_##arr##_count, \
(void)_##arr##_tmp, \
(void)_##arr##_static
/* not part of the 'API' but handy funcs,
* same purpose as BLI_array_staticdeclare()
* but use when the max size is known ahead of time */
#define BLI_array_fixedstack_declare(arr, maxstatic, realsize, allocstr) \
char _##arr##_static[maxstatic*sizeof(*arr)]; \
const int _##arr##_is_static= ((void *)_##arr##_static) != ( \
arr= (realsize <= maxstatic) ? \
(void *)_##arr##_static : \
MEM_mallocN(sizeof(*arr)*realsize, allocstr) \
) \
#define BLI_array_fixedstack_free(arr) \
if (_##arr##_is_static) MEM_freeN(arr) \

@ -47,22 +47,22 @@ void BLI_edgehash_free (EdgeHash *eh, EdgeHashFreeFP valfreefp);
/* Insert edge (v0,v1) into hash with given value, does /* Insert edge (v0,v1) into hash with given value, does
* not check for duplicates. * not check for duplicates.
*/ */
void BLI_edgehash_insert (EdgeHash *eh, int v0, int v1, void *val); void BLI_edgehash_insert (EdgeHash *eh, unsigned int v0, unsigned int v1, void *val);
/* Return value for given edge (v0,v1), or NULL if /* Return value for given edge (v0,v1), or NULL if
* if key does not exist in hash. (If need exists * if key does not exist in hash. (If need exists
* to differentiate between key-value being NULL and * to differentiate between key-value being NULL and
* lack of key then see BLI_edgehash_lookup_p(). * lack of key then see BLI_edgehash_lookup_p().
*/ */
void* BLI_edgehash_lookup (EdgeHash *eh, int v0, int v1); void* BLI_edgehash_lookup (EdgeHash *eh, unsigned int v0, unsigned int v1);
/* Return pointer to value for given edge (v0,v1), /* Return pointer to value for given edge (v0,v1),
* or NULL if key does not exist in hash. * or NULL if key does not exist in hash.
*/ */
void** BLI_edgehash_lookup_p (EdgeHash *eh, int v0, int v1); void** BLI_edgehash_lookup_p (EdgeHash *eh, unsigned int v0, unsigned int v1);
/* Return boolean true/false if edge (v0,v1) in hash. */ /* Return boolean true/false if edge (v0,v1) in hash. */
int BLI_edgehash_haskey (EdgeHash *eh, int v0, int v1); int BLI_edgehash_haskey (EdgeHash *eh, unsigned int v0, unsigned int v1);
/* Return number of keys in hash. */ /* Return number of keys in hash. */
int BLI_edgehash_size (EdgeHash *eh); int BLI_edgehash_size (EdgeHash *eh);
@ -83,7 +83,7 @@ EdgeHashIterator* BLI_edgehashIterator_new (EdgeHash *eh);
void BLI_edgehashIterator_free (EdgeHashIterator *ehi); void BLI_edgehashIterator_free (EdgeHashIterator *ehi);
/* Retrieve the key from an iterator. */ /* Retrieve the key from an iterator. */
void BLI_edgehashIterator_getKey (EdgeHashIterator *ehi, int *v0_r, int *v1_r); void BLI_edgehashIterator_getKey (EdgeHashIterator *ehi, unsigned int *v0_r, unsigned int *v1_r);
/* Retrieve the value from an iterator. */ /* Retrieve the value from an iterator. */
void* BLI_edgehashIterator_getValue (EdgeHashIterator *ehi); void* BLI_edgehashIterator_getValue (EdgeHashIterator *ehi);
@ -98,4 +98,3 @@ void BLI_edgehashIterator_step (EdgeHashIterator *ehi);
int BLI_edgehashIterator_isDone (EdgeHashIterator *ehi); int BLI_edgehashIterator_isDone (EdgeHashIterator *ehi);
#endif #endif

@ -34,6 +34,8 @@
extern "C" { extern "C" {
#endif #endif
#include "BLI_math_inline.h"
/* primaries */ /* primaries */
#define BLI_XYZ_SMPTE 0 #define BLI_XYZ_SMPTE 0
#define BLI_XYZ_REC709_SRGB 1 #define BLI_XYZ_REC709_SRGB 1
@ -70,21 +72,22 @@ unsigned int hsv_to_cpack(float h, float s, float v);
float rgb_to_grayscale(float rgb[3]); float rgb_to_grayscale(float rgb[3]);
unsigned char rgb_to_grayscale_byte(unsigned char rgb[3]); unsigned char rgb_to_grayscale_byte(unsigned char rgb[3]);
/***************** Profile Transformations ********************/ /**************** Profile Transformations *****************/
void gamma_correct(float *c, float gamma); void gamma_correct(float *c, float gamma);
float rec709_to_linearrgb(float c); float rec709_to_linearrgb(float c);
float linearrgb_to_rec709(float c); float linearrgb_to_rec709(float c);
float srgb_to_linearrgb(float c); float srgb_to_linearrgb(float c);
float linearrgb_to_srgb(float c); float linearrgb_to_srgb(float c);
void srgb_to_linearrgb_v3_v3(float *col_to, float *col_from);
void linearrgb_to_srgb_v3_v3(float *col_to, float *col_from);
/* rgba buffer convenience functions */ MINLINE void srgb_to_linearrgb_v3_v3(float linear[3], const float srgb[3]);
void srgb_to_linearrgb_rgba_buf(float *col, int tot); MINLINE void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3]);
void linearrgb_to_srgb_rgba_buf(float *col, int tot);
void srgb_to_linearrgb_rgba_rgba_buf(float *col_to, float *col_from, int tot); MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4]);
void linearrgb_to_srgb_rgba_rgba_buf(float *col_to, float *col_from, int tot); MINLINE void linearrgb_to_srgb_v4(float srgb[4], const float linear[4]);
MINLINE void srgb_to_linearrgb_predivide_v4(float linear[4], const float srgb[4]);
MINLINE void linearrgb_to_srgb_predivide_v4(float srgb[4], const float linear[4]);
/************************** Other *************************/ /************************** Other *************************/
@ -101,6 +104,10 @@ void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, float *o
void rgb_byte_to_float(const unsigned char *in, float *out); void rgb_byte_to_float(const unsigned char *in, float *out);
void rgb_float_to_byte(const float *in, unsigned char *out); void rgb_float_to_byte(const float *in, unsigned char *out);
#ifdef BLI_MATH_INLINE_H
#include "intern/math_color_inline.c"
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -300,4 +300,13 @@
# define BLI_assert(a) (void)0 # define BLI_assert(a) (void)0
#endif #endif
/* hints for branch pradiction, only use in code that runs a _lot_ where */
#ifdef __GNUC__
# define LIKELY(x) __builtin_expect(!!(x), 1)
# define UNLIKELY(x) __builtin_expect(!!(x), 0)
#else
# define LIKELY(x) (x)
# define UNLIKELY(x) (x)
#endif
#endif // BLI_UTILDEFINES_H #endif // BLI_UTILDEFINES_H

@ -66,6 +66,7 @@ set(SRC
intern/math_base.c intern/math_base.c
intern/math_base_inline.c intern/math_base_inline.c
intern/math_color.c intern/math_color.c
intern/math_color_inline.c
intern/math_geom.c intern/math_geom.c
intern/math_geom_inline.c intern/math_geom_inline.c
intern/math_matrix.c intern/math_matrix.c
@ -88,6 +89,7 @@ set(SRC
intern/voxel.c intern/voxel.c
intern/winstuff.c intern/winstuff.c
BLI_array.h
BLI_args.h BLI_args.h
BLI_blenlib.h BLI_blenlib.h
BLI_boxpack2d.h BLI_boxpack2d.h

@ -274,6 +274,9 @@ void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter)
iter->curindex = 0; iter->curindex = 0;
} }
#if 0
/* unoptimized, more readable */
static void *bli_mempool_iternext(BLI_mempool_iter *iter) static void *bli_mempool_iternext(BLI_mempool_iter *iter)
{ {
void *ret = NULL; void *ret = NULL;
@ -303,6 +306,37 @@ void *BLI_mempool_iterstep(BLI_mempool_iter *iter)
return ret; return ret;
} }
#else
/* optimized version of code above */
void *BLI_mempool_iterstep(BLI_mempool_iter *iter)
{
BLI_freenode *ret;
if (UNLIKELY(iter->pool->totused == 0)) {
return NULL;
}
do {
if (LIKELY(iter->curchunk)) {
ret = (BLI_freenode *)(((char*)iter->curchunk->data) + iter->pool->esize*iter->curindex);
}
else {
return NULL;
}
if (UNLIKELY(++iter->curindex >= iter->pool->pchunk)) {
iter->curindex = 0;
iter->curchunk = iter->curchunk->next;
}
} while (ret->freeword == FREEWORD);
return ret;
}
#endif
void BLI_mempool_destroy(BLI_mempool *pool) void BLI_mempool_destroy(BLI_mempool *pool)
{ {
BLI_mempool_chunk *mpchunk=NULL; BLI_mempool_chunk *mpchunk=NULL;

@ -20,7 +20,7 @@
* *
* The Original Code is: none of this file. * The Original Code is: none of this file.
* *
* Contributor(s): Daniel Dunbar * Contributor(s): Daniel Dunbar, Joseph Eagar
* *
* ***** END GPL LICENSE BLOCK ***** * ***** END GPL LICENSE BLOCK *****
* A general (pointer -> pointer) hash table ADT * A general (pointer -> pointer) hash table ADT
@ -35,30 +35,41 @@
#include <string.h> #include <string.h>
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
#include "BLI_edgehash.h" #include "BLI_edgehash.h"
#include "BLI_mempool.h"
/***/ /**************inlined code************/
static unsigned int _ehash_hashsizes[]= {
static unsigned int hashsizes[]= {
1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, 1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209,
16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169, 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169,
4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 4194319, 8388617, 16777259, 33554467, 67108879, 134217757,
268435459 268435459
}; };
#define EDGEHASH(v0,v1) ((v0*39)^(v1*31)) #define EDGE_HASH(v0, v1) ((v0 * 39)^(v1 * 31))
/* ensure v0 is smaller */
#define EDGE_ORD(v0, v1) \
if (v0 > v1) { \
v0 ^= v1; \
v1 ^= v0; \
v0 ^= v1; \
}
/***/ /***/
typedef struct Entry Entry; typedef struct EdgeEntry EdgeEntry;
struct Entry { struct EdgeEntry {
Entry *next; EdgeEntry *next;
int v0, v1; unsigned int v0, v1;
void *val; void *val;
}; };
struct EdgeHash { struct EdgeHash {
Entry **buckets; EdgeEntry **buckets;
BLI_mempool *epool;
int nbuckets, nentries, cursize; int nbuckets, nentries, cursize;
}; };
@ -66,87 +77,82 @@ struct EdgeHash {
EdgeHash *BLI_edgehash_new(void) EdgeHash *BLI_edgehash_new(void)
{ {
EdgeHash *eh= MEM_mallocN(sizeof(*eh), "EdgeHash"); EdgeHash *eh = MEM_callocN(sizeof(*eh), "EdgeHash");
eh->cursize= 0; eh->cursize = 0;
eh->nentries= 0; eh->nentries = 0;
eh->nbuckets= hashsizes[eh->cursize]; eh->nbuckets = _ehash_hashsizes[eh->cursize];
eh->buckets= malloc(eh->nbuckets*sizeof(*eh->buckets)); eh->buckets = MEM_callocN(eh->nbuckets * sizeof(*eh->buckets), "eh buckets 2");
memset(eh->buckets, 0, eh->nbuckets*sizeof(*eh->buckets)); eh->epool = BLI_mempool_create(sizeof(EdgeEntry), 512, 512, TRUE, FALSE);
return eh; return eh;
} }
void BLI_edgehash_insert(EdgeHash *eh, int v0, int v1, void *val)
void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val)
{ {
unsigned int hash; unsigned int hash;
Entry *e= malloc(sizeof(*e)); EdgeEntry *e = BLI_mempool_alloc(eh->epool);
if (v1<v0) { EDGE_ORD(v0, v1); /* ensure v0 is smaller */
v0 ^= v1;
v1 ^= v0; hash = EDGE_HASH(v0, v1) % eh->nbuckets;
v0 ^= v1;
}
hash = EDGEHASH(v0,v1)%eh->nbuckets;
e->v0 = v0; e->v0 = v0;
e->v1 = v1; e->v1 = v1;
e->val = val; e->val = val;
e->next= eh->buckets[hash]; e->next = eh->buckets[hash];
eh->buckets[hash]= e; eh->buckets[hash]= e;
if (++eh->nentries>eh->nbuckets*3) { if (++eh->nentries>eh->nbuckets * 3) {
Entry **old= eh->buckets; EdgeEntry *e, **old = eh->buckets;
int i, nold= eh->nbuckets; int i, nold = eh->nbuckets;
eh->nbuckets= hashsizes[++eh->cursize]; eh->nbuckets = _ehash_hashsizes[++eh->cursize];
eh->buckets= malloc(eh->nbuckets*sizeof(*eh->buckets)); eh->buckets = MEM_mallocN(eh->nbuckets * sizeof(*eh->buckets), "eh buckets");
memset(eh->buckets, 0, eh->nbuckets*sizeof(*eh->buckets)); memset(eh->buckets, 0, eh->nbuckets * sizeof(*eh->buckets));
for (i=0; i<nold; i++) { for (i = 0; i < nold; i++) {
for (e= old[i]; e;) { for (e = old[i]; e;) {
Entry *n= e->next; EdgeEntry *n = e->next;
hash= EDGEHASH(e->v0,e->v1)%eh->nbuckets; hash = EDGE_HASH(e->v0, e->v1) % eh->nbuckets;
e->next= eh->buckets[hash]; e->next = eh->buckets[hash];
eh->buckets[hash]= e; eh->buckets[hash]= e;
e= n; e = n;
} }
} }
free(old); MEM_freeN(old);
} }
} }
void** BLI_edgehash_lookup_p(EdgeHash *eh, int v0, int v1) void **BLI_edgehash_lookup_p(EdgeHash *eh, unsigned int v0, unsigned int v1)
{ {
unsigned int hash; unsigned int hash;
Entry *e; EdgeEntry *e;
if (v1<v0) { EDGE_ORD(v0, v1); /* ensure v0 is smaller */
v0 ^= v1;
v1 ^= v0; hash = EDGE_HASH(v0, v1) % eh->nbuckets;
v0 ^= v1; for (e = eh->buckets[hash]; e; e = e->next)
} if (v0 == e->v0 && v1 == e->v1)
hash = EDGEHASH(v0,v1)%eh->nbuckets;
for (e= eh->buckets[hash]; e; e= e->next)
if (v0==e->v0 && v1==e->v1)
return &e->val; return &e->val;
return NULL; return NULL;
} }
void* BLI_edgehash_lookup(EdgeHash *eh, int v0, int v1) void *BLI_edgehash_lookup(EdgeHash *eh, unsigned int v0, unsigned int v1)
{ {
void **value_p = BLI_edgehash_lookup_p(eh,v0,v1); void **value_p = BLI_edgehash_lookup_p(eh, v0, v1);
return value_p?*value_p:NULL; return value_p?*value_p:NULL;
} }
int BLI_edgehash_haskey(EdgeHash *eh, int v0, int v1) int BLI_edgehash_haskey(EdgeHash *eh, unsigned int v0, unsigned int v1)
{ {
return BLI_edgehash_lookup_p(eh, v0, v1)!=NULL; return BLI_edgehash_lookup_p(eh, v0, v1) != NULL;
} }
int BLI_edgehash_size(EdgeHash *eh) int BLI_edgehash_size(EdgeHash *eh)
@ -158,28 +164,30 @@ void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp)
{ {
int i; int i;
for (i=0; i<eh->nbuckets; i++) { for (i = 0; i<eh->nbuckets; i++) {
Entry *e; EdgeEntry *e;
for (e= eh->buckets[i]; e; ) { for (e = eh->buckets[i]; e; ) {
Entry *n= e->next; EdgeEntry *n = e->next;
if (valfreefp) valfreefp(e->val); if (valfreefp) valfreefp(e->val);
free(e); BLI_mempool_free(eh->epool, e);
e= n; e = n;
} }
eh->buckets[i]= NULL; eh->buckets[i] = NULL;
} }
eh->nentries= 0; eh->nentries = 0;
} }
void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp) void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp)
{ {
BLI_edgehash_clear(eh, valfreefp); BLI_edgehash_clear(eh, valfreefp);
free(eh->buckets); BLI_mempool_destroy(eh->epool);
MEM_freeN(eh->buckets);
MEM_freeN(eh); MEM_freeN(eh);
} }
@ -189,29 +197,29 @@ void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp)
struct EdgeHashIterator { struct EdgeHashIterator {
EdgeHash *eh; EdgeHash *eh;
int curBucket; int curBucket;
Entry *curEntry; EdgeEntry *curEntry;
}; };
EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh) EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh)
{ {
EdgeHashIterator *ehi= malloc(sizeof(*ehi)); EdgeHashIterator *ehi = MEM_mallocN(sizeof(*ehi), "eh iter");
ehi->eh= eh; ehi->eh = eh;
ehi->curEntry= NULL; ehi->curEntry = NULL;
ehi->curBucket= -1; ehi->curBucket = -1;
while (!ehi->curEntry) { while (!ehi->curEntry) {
ehi->curBucket++; ehi->curBucket++;
if (ehi->curBucket==ehi->eh->nbuckets) if (ehi->curBucket == ehi->eh->nbuckets)
break; break;
ehi->curEntry= ehi->eh->buckets[ehi->curBucket]; ehi->curEntry = ehi->eh->buckets[ehi->curBucket];
} }
return ehi; return ehi;
} }
void BLI_edgehashIterator_free(EdgeHashIterator *ehi) void BLI_edgehashIterator_free(EdgeHashIterator *ehi)
{ {
free(ehi); MEM_freeN(ehi);
} }
void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, int *v0_r, int *v1_r) void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, unsigned int *v0_r, unsigned int *v1_r)
{ {
if (ehi->curEntry) { if (ehi->curEntry) {
*v0_r = ehi->curEntry->v0; *v0_r = ehi->curEntry->v0;
@ -225,19 +233,22 @@ void *BLI_edgehashIterator_getValue(EdgeHashIterator *ehi)
void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val) void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val)
{ {
if(ehi->curEntry) if (ehi->curEntry) {
ehi->curEntry->val= val; ehi->curEntry->val = val;
}
} }
void BLI_edgehashIterator_step(EdgeHashIterator *ehi) void BLI_edgehashIterator_step(EdgeHashIterator *ehi)
{ {
if (ehi->curEntry) { if (ehi->curEntry) {
ehi->curEntry= ehi->curEntry->next; ehi->curEntry = ehi->curEntry->next;
while (!ehi->curEntry) { while (!ehi->curEntry) {
ehi->curBucket++; ehi->curBucket++;
if (ehi->curBucket==ehi->eh->nbuckets) if (ehi->curBucket == ehi->eh->nbuckets) {
break; break;
ehi->curEntry= ehi->eh->buckets[ehi->curBucket]; }
ehi->curEntry = ehi->eh->buckets[ehi->curBucket];
} }
} }
} }

@ -393,57 +393,6 @@ float linearrgb_to_srgb(float c)
return 1.055f * powf(c, 1.0f/2.4f) - 0.055f; return 1.055f * powf(c, 1.0f/2.4f) - 0.055f;
} }
void srgb_to_linearrgb_v3_v3(float *col_to, float *col_from)
{
col_to[0] = srgb_to_linearrgb(col_from[0]);
col_to[1] = srgb_to_linearrgb(col_from[1]);
col_to[2] = srgb_to_linearrgb(col_from[2]);
}
void linearrgb_to_srgb_v3_v3(float *col_to, float *col_from)
{
col_to[0] = linearrgb_to_srgb(col_from[0]);
col_to[1] = linearrgb_to_srgb(col_from[1]);
col_to[2] = linearrgb_to_srgb(col_from[2]);
}
/* todo, should these be moved elsewhere?, they dont belong in imbuf */
void srgb_to_linearrgb_rgba_buf(float *col, int tot)
{
while(tot--) {
srgb_to_linearrgb_v3_v3(col, col);
col += 4;
}
}
void linearrgb_to_srgb_rgba_buf(float *col, int tot)
{
while(tot--) {
linearrgb_to_srgb_v3_v3(col, col);
col += 4;
}
}
void srgb_to_linearrgb_rgba_rgba_buf(float *col_to, float *col_from, int tot)
{
while(tot--) {
srgb_to_linearrgb_v3_v3(col_to, col_from);
col_to[3]= col_from[3];
col_to += 4;
col_from += 4;
}
}
void linearrgb_to_srgb_rgba_rgba_buf(float *col_to, float *col_from, int tot)
{
while(tot--) {
linearrgb_to_srgb_v3_v3(col_to, col_from);
col_to[3]= col_from[3];
col_to += 4;
col_from += 4;
}
}
void minmax_rgb(short c[]) void minmax_rgb(short c[])
{ {
if(c[0]>255) c[0]=255; if(c[0]>255) c[0]=255;

@ -0,0 +1,109 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: some of this file.
*
* ***** END GPL LICENSE BLOCK *****
* */
/** \file blender/blenlib/intern/math_color_inline.c
* \ingroup bli
*/
#include "BLI_math_color.h"
#include "BLI_utildefines.h"
#ifndef BLI_MATH_COLOR_INLINE_H
#define BLI_MATH_COLOR_INLINE_H
/******************************** Color Space ********************************/
MINLINE void srgb_to_linearrgb_v3_v3(float linear[3], const float srgb[3])
{
linear[0] = srgb_to_linearrgb(srgb[0]);
linear[1] = srgb_to_linearrgb(srgb[1]);
linear[2] = srgb_to_linearrgb(srgb[2]);
}
MINLINE void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3])
{
srgb[0] = linearrgb_to_srgb(linear[0]);
srgb[1] = linearrgb_to_srgb(linear[1]);
srgb[2] = linearrgb_to_srgb(linear[2]);
}
MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4])
{
srgb_to_linearrgb_v3_v3(linear, srgb);
linear[3] = srgb[3];
}
MINLINE void linearrgb_to_srgb_v4(float srgb[4], const float linear[4])
{
linearrgb_to_srgb_v3_v3(srgb, linear);
srgb[3] = linear[3];
}
/* predivide versions to work on associated/premultipled alpha. if this should
be done or not depends on the background the image will be composited over,
ideally you would never do color space conversion on an image with alpha
because it is ill defined */
MINLINE void srgb_to_linearrgb_predivide_v4(float linear[4], const float srgb[4])
{
float alpha, inv_alpha;
if(srgb[3] == 1.0f || srgb[3] == 0.0f) {
alpha = 1.0f;
inv_alpha = 1.0f;
}
else {
alpha = srgb[3];
inv_alpha = 1.0f/alpha;
}
linear[0] = srgb_to_linearrgb(srgb[0] * inv_alpha) * alpha;
linear[1] = srgb_to_linearrgb(srgb[1] * inv_alpha) * alpha;
linear[2] = srgb_to_linearrgb(srgb[2] * inv_alpha) * alpha;
linear[3] = srgb[3];
}
MINLINE void linearrgb_to_srgb_predivide_v4(float srgb[4], const float linear[4])
{
float alpha, inv_alpha;
if(linear[3] == 1.0f || linear[3] == 0.0f) {
alpha = 1.0f;
inv_alpha = 1.0f;
}
else {
alpha = linear[3];
inv_alpha = 1.0f/alpha;
}
srgb[0] = linearrgb_to_srgb(linear[0] * inv_alpha) * alpha;
srgb[1] = linearrgb_to_srgb(linear[1] * inv_alpha) * alpha;
srgb[2] = linearrgb_to_srgb(linear[2] * inv_alpha) * alpha;
srgb[3] = linear[3];
}
#endif /* BLI_MATH_COLOR_INLINE_H */

@ -195,8 +195,14 @@ void mul_m3_m3m3(float m1[][3], float m3_[][3], float m2_[][3])
m1[2][2]= m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2]; m1[2][2]= m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2];
} }
void mul_m4_m4m3(float (*m1)[4], float (*m3)[4], float (*m2)[3]) void mul_m4_m4m3(float (*m1)[4], float (*m3_)[4], float (*m2_)[3])
{ {
float m2[3][3], m3[4][4];
/* copy so it works when m1 is the same pointer as m2 or m3 */
copy_m3_m3(m2, m2_);
copy_m4_m4(m3, m3_);
m1[0][0]= m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0]; m1[0][0]= m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0];
m1[0][1]= m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1]; m1[0][1]= m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1];
m1[0][2]= m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2]; m1[0][2]= m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2];

Some files were not shown because too many files have changed in this diff Show More