Merging r42945 through r43024 from trunk into soc-2011-tomato
authorSergey Sharybin <sergey.vfx@gmail.com>
Sat, 31 Dec 2011 09:23:06 +0000 (09:23 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Sat, 31 Dec 2011 09:23:06 +0000 (09:23 +0000)
200 files changed:
CMakeLists.txt
SConstruct
build_files/cmake/macros.cmake
build_files/scons/config/win32-mingw-config.py
build_files/scons/tools/btools.py
extern/CMakeLists.txt
intern/CMakeLists.txt
intern/SConscript
intern/bsp/test/BSP_GhostTest/BSP_GhostTest3D.cpp
intern/cycles/CMakeLists.txt
intern/cycles/blender/blender_camera.cpp
intern/cycles/blender/blender_shader.cpp
intern/cycles/kernel/osl/nodes/node_hsv.osl
intern/cycles/kernel/svm/svm_hsv.h
intern/cycles/kernel/svm/svm_normal.h
intern/dualcon/CMakeLists.txt [new file with mode: 0644]
intern/dualcon/SConscript [new file with mode: 0644]
intern/dualcon/dualcon.h [new file with mode: 0644]
intern/dualcon/intern/GeoCommon.h [new file with mode: 0644]
intern/dualcon/intern/MemoryAllocator.h [new file with mode: 0644]
intern/dualcon/intern/ModelReader.h [new file with mode: 0644]
intern/dualcon/intern/Projections.cpp [new file with mode: 0644]
intern/dualcon/intern/Projections.h [new file with mode: 0644]
intern/dualcon/intern/Queue.h [new file with mode: 0644]
intern/dualcon/intern/cubes.h [new file with mode: 0644]
intern/dualcon/intern/dualcon_c_api.cpp [new file with mode: 0644]
intern/dualcon/intern/manifold_table.cpp [new file with mode: 0644]
intern/dualcon/intern/manifold_table.h [new file with mode: 0644]
intern/dualcon/intern/marching_cubes_table.cpp [new file with mode: 0644]
intern/dualcon/intern/marching_cubes_table.h [new file with mode: 0644]
intern/dualcon/intern/octree.cpp [new file with mode: 0644]
intern/dualcon/intern/octree.h [new file with mode: 0644]
intern/dualcon/intern/readme.txt [new file with mode: 0644]
intern/ghost/intern/GHOST_SystemCarbon.cpp
intern/ghost/intern/GHOST_SystemCocoa.mm
intern/ghost/intern/GHOST_SystemX11.cpp
intern/ghost/intern/GHOST_WindowCarbon.cpp
intern/ghost/intern/GHOST_WindowWin32.cpp
intern/ghost/intern/GHOST_WindowX11.cpp
intern/guardedalloc/MEM_sys_types.h
intern/smoke/intern/smoke_API.cpp
release/datafiles/blender_icons.png
release/plugins/sequence/color-correction-hsv.c
release/plugins/sequence/color-correction-yuv.c
release/plugins/sequence/dnr.c
release/plugins/sequence/gamma.c
release/scripts/modules/bpy/utils.py
release/scripts/startup/bl_operators/presets.py
release/scripts/startup/bl_ui/properties_data_modifier.py
release/scripts/startup/bl_ui/properties_game.py
release/scripts/startup/bl_ui/properties_render.py
release/scripts/startup/bl_ui/space_clip.py
source/blender/blenkernel/BKE_array_mallocn.h
source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/intern/brush.c
source/blender/blenkernel/intern/constraint.c
source/blender/blenkernel/intern/customdata.c
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenkernel/intern/image.c
source/blender/blenkernel/intern/mesh.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/sequencer.c
source/blender/blenkernel/intern/tracking.c
source/blender/blenlib/BLI_utildefines.h
source/blender/blenlib/CMakeLists.txt
source/blender/blenlib/intern/BLI_mempool.c
source/blender/blenloader/BLO_sys_types.h
source/blender/collada/MeshImporter.cpp
source/blender/editors/curve/curve_intern.h
source/blender/editors/curve/curve_ops.c
source/blender/editors/curve/editfont.c
source/blender/editors/datafiles/blender_icons.png.c
source/blender/editors/include/BIF_glutil.h
source/blender/editors/include/UI_icons.h
source/blender/editors/mesh/editmesh_mods.c
source/blender/editors/mesh/editmesh_tools.c
source/blender/editors/object/object_bake.c
source/blender/editors/physics/physics_fluid.c
source/blender/editors/render/render_internal.c
source/blender/editors/render/render_preview.c
source/blender/editors/screen/glutil.c
source/blender/editors/sculpt_paint/paint_vertex.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/editors/space_clip/tracking_ops.c
source/blender/editors/space_file/filesel.c
source/blender/editors/space_image/image_buttons.c
source/blender/editors/space_node/space_node.c
source/blender/editors/space_outliner/outliner_draw.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/editors/space_view3d/view3d_snap.c
source/blender/gpu/intern/gpu_shader_material.glsl
source/blender/gpu/intern/gpu_shader_material.glsl.c
source/blender/imbuf/IMB_imbuf_types.h
source/blender/imbuf/intern/divers.c
source/blender/makesdna/DNA_ID.h
source/blender/makesdna/DNA_action_types.h
source/blender/makesdna/DNA_anim_types.h
source/blender/makesdna/DNA_armature_types.h
source/blender/makesdna/DNA_boid_types.h
source/blender/makesdna/DNA_brush_types.h
source/blender/makesdna/DNA_camera_types.h
source/blender/makesdna/DNA_cloth_types.h
source/blender/makesdna/DNA_color_types.h
source/blender/makesdna/DNA_constraint_types.h
source/blender/makesdna/DNA_controller_types.h
source/blender/makesdna/DNA_curve_types.h
source/blender/makesdna/DNA_customdata_types.h
source/blender/makesdna/DNA_defs.h
source/blender/makesdna/DNA_dynamicpaint_types.h
source/blender/makesdna/DNA_effect_types.h
source/blender/makesdna/DNA_fileglobal_types.h
source/blender/makesdna/DNA_genfile.h
source/blender/makesdna/DNA_gpencil_types.h
source/blender/makesdna/DNA_group_types.h
source/blender/makesdna/DNA_image_types.h
source/blender/makesdna/DNA_lamp_types.h
source/blender/makesdna/DNA_lattice_types.h
source/blender/makesdna/DNA_listBase.h
source/blender/makesdna/DNA_material_types.h
source/blender/makesdna/DNA_mesh_types.h
source/blender/makesdna/DNA_meshdata_types.h
source/blender/makesdna/DNA_meta_types.h
source/blender/makesdna/DNA_modifier_types.h
source/blender/makesdna/DNA_movieclip_types.h
source/blender/makesdna/DNA_nla_types.h
source/blender/makesdna/DNA_node_types.h
source/blender/makesdna/DNA_object_fluidsim.h
source/blender/makesdna/DNA_object_force.h
source/blender/makesdna/DNA_object_types.h
source/blender/makesdna/DNA_outliner_types.h
source/blender/makesdna/DNA_packedFile_types.h
source/blender/makesdna/DNA_particle_types.h
source/blender/makesdna/DNA_property_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_screen_types.h
source/blender/makesdna/DNA_sdna_types.h
source/blender/makesdna/DNA_sensor_types.h
source/blender/makesdna/DNA_sequence_types.h
source/blender/makesdna/DNA_smoke_types.h
source/blender/makesdna/DNA_sound_types.h
source/blender/makesdna/DNA_space_types.h
source/blender/makesdna/DNA_speaker_types.h
source/blender/makesdna/DNA_text_types.h
source/blender/makesdna/DNA_texture_types.h
source/blender/makesdna/DNA_tracking_types.h
source/blender/makesdna/DNA_userdef_types.h
source/blender/makesdna/DNA_vec_types.h
source/blender/makesdna/DNA_vfont_types.h
source/blender/makesdna/DNA_view2d_types.h
source/blender/makesdna/DNA_view3d_types.h
source/blender/makesdna/DNA_windowmanager_types.h
source/blender/makesdna/DNA_world_types.h
source/blender/makesrna/intern/rna_image.c
source/blender/makesrna/intern/rna_modifier.c
source/blender/makesrna/intern/rna_scene.c
source/blender/modifiers/CMakeLists.txt
source/blender/modifiers/MOD_modifiertypes.h
source/blender/modifiers/SConscript
source/blender/modifiers/intern/MOD_mirror.c
source/blender/modifiers/intern/MOD_remesh.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_util.c
source/blender/nodes/composite/node_composite_util.c
source/blender/nodes/composite/nodes/node_composite_image.c
source/blender/nodes/shader/nodes/node_shader_dynamic.c
source/blender/python/intern/CMakeLists.txt
source/blender/python/intern/bpy_rna.c
source/blender/python/mathutils/mathutils_Matrix.c
source/blender/quicktime/apple/qtkit_export.m
source/blender/quicktime/apple/qtkit_import.m
source/blender/quicktime/apple/quicktime_export.c
source/blender/quicktime/apple/quicktime_import.c
source/blender/render/intern/source/pipeline.c
source/blenderplayer/bad_level_call_stubs/stubs.c
source/creator/CMakeLists.txt
source/gameengine/Converter/BL_ActionActuator.cpp
source/gameengine/Converter/BL_BlenderDataConversion.cpp
source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp
source/gameengine/Converter/KX_BlenderSceneConverter.cpp
source/gameengine/Converter/KX_IpoConvert.cpp
source/gameengine/Expressions/InputParser.cpp
source/gameengine/Expressions/Operator1Expr.cpp
source/gameengine/Expressions/Operator2Expr.cpp
source/gameengine/Expressions/PyObjectPlus.h
source/gameengine/Expressions/StringValue.h
source/gameengine/Expressions/Value.cpp
source/gameengine/Expressions/Value.h
source/gameengine/GameLogic/SCA_ISensor.cpp
source/gameengine/GameLogic/SCA_RandomActuator.cpp
source/gameengine/GameLogic/SCA_RandomNumberGenerator.cpp
source/gameengine/Ketsji/BL_Material.cpp
source/gameengine/Ketsji/BL_Texture.cpp
source/gameengine/Ketsji/KX_BlenderMaterial.h
source/gameengine/Ketsji/KX_Dome.cpp
source/gameengine/Ketsji/KX_FontObject.cpp
source/gameengine/Ketsji/KX_FontObject.h
source/gameengine/Ketsji/KX_GameObject.h
source/gameengine/Ketsji/KX_MeshProxy.cpp
source/gameengine/Ketsji/KX_Scene.h
source/gameengine/Ketsji/KX_TouchSensor.cpp

index a7e9de026e48e7f25fcf203f771e2587c0b18832..40a51f0b45249a0ee5229841df081dd651480c72 100644 (file)
@@ -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_DECIMATE               "Enable Decimate 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)
 mark_as_advanced(WITH_MOD_CLOTH_ELTOPO)
 option(WITH_MOD_OCEANSIM        "Enable Ocean Modifier" OFF)
@@ -765,22 +766,27 @@ elseif(WIN32)
                                ${LIBDIR}/opencollada/include/COLLADASaxFrameworkLoader/include
                                ${LIBDIR}/opencollada/include/GeneratedSaxParser/include
                        )
+                       
+                       set_lib_path(OPENCOLLADA_LIBPATH "opencollada/lib")
 
                        set(OPENCOLLADA_LIBRARIES
-                               ${LIBDIR}/opencollada/lib/OpenCOLLADASaxFrameworkLoader.lib
-                               ${LIBDIR}/opencollada/lib/OpenCOLLADAFramework.lib
-                               ${LIBDIR}/opencollada/lib/OpenCOLLADABaseUtils.lib
-                               ${LIBDIR}/opencollada/lib/OpenCOLLADAStreamWriter.lib
-                               ${LIBDIR}/opencollada/lib/MathMLSolver.lib
-                               ${LIBDIR}/opencollada/lib/GeneratedSaxParser.lib
-                               ${LIBDIR}/opencollada/lib/xml2.lib
-                               ${LIBDIR}/opencollada/lib/buffer.lib
-                               ${LIBDIR}/opencollada/lib/ftoa.lib
-                               ${LIBDIR}/opencollada/lib/UTF.lib
+                               ${OPENCOLLADA_LIBPATH}/OpenCOLLADASaxFrameworkLoader.lib
+                               ${OPENCOLLADA_LIBPATH}/OpenCOLLADAFramework.lib
+                               ${OPENCOLLADA_LIBPATH}/OpenCOLLADABaseUtils.lib
+                               ${OPENCOLLADA_LIBPATH}/OpenCOLLADAStreamWriter.lib
+                               ${OPENCOLLADA_LIBPATH}/MathMLSolver.lib
+                               ${OPENCOLLADA_LIBPATH}/GeneratedSaxParser.lib
+                               ${OPENCOLLADA_LIBPATH}/xml2.lib
+                               ${OPENCOLLADA_LIBPATH}/buffer.lib
+                               ${OPENCOLLADA_LIBPATH}/ftoa.lib
+                               ${OPENCOLLADA_LIBPATH}/UTF.lib
                        )
                        set(PCRE_LIBRARIES
-                               ${LIBDIR}/opencollada/lib/pcre.lib
+                               ${OPENCOLLADA_LIBPATH}/pcre.lib
                        )
+                       
+                       unset(OPENCOLLADA_LIBPATH)
+                       
                endif()
 
                if(WITH_CODEC_FFMPEG)
@@ -798,18 +804,8 @@ elseif(WIN32)
                endif()
 
                if(WITH_IMAGE_OPENEXR)
-                       if(MSVC90)
-                               set(MSVC_LIB _vs2008)
-                               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_lib_path(OPENEXR "openexr")
+                       set_lib_path(OPENEXR_LIBPATH "openexr/lib")
                        set(OPENEXR_LIBRARIES
                                ${OPENEXR_LIBPATH}/Iex.lib
                                ${OPENEXR_LIBPATH}/Half.lib
@@ -817,7 +813,7 @@ elseif(WIN32)
                                ${OPENEXR_LIBPATH}/Imath.lib
                                ${OPENEXR_LIBPATH}/IlmThread.lib
                        )
-                       set(OPENEXR_INCUDE ${OPENEXR}/include${MSVC_INC})
+                       set_lib_path(OPENEXR_INCUDE "openexr/include")
                        set(OPENEXR_INCLUDE_DIRS
                                ${OPENEXR_INCUDE}
                                ${OPENEXR_INCUDE}/IlmImf
@@ -844,9 +840,9 @@ elseif(WIN32)
                if(WITH_PYTHON)
                        # normally cached but not since we include them with blender
                        set(PYTHON_VERSION 3.2) # CACHE STRING)
-                       set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}") # CACHE PATH)
-                       set(PYTHON_LIBRARY "${LIBDIR}/python/lib/python32.lib") #CACHE FILEPATH)
-
+                       set_lib_path(PYTHON_INCLUDE_DIR "python/include/python${PYTHON_VERSION}")
+                       set_lib_path(PYTHON_LIBRARY "python/lib/python32.lib") #CACHE FILEPATH)
+                       
                        # uncached vars
                        set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}")
                        set(PYTHON_LIBRARIES  "${PYTHON_LIBRARY}")
@@ -879,7 +875,7 @@ elseif(WIN32)
                        set(OPENIMAGEIO ${LIBDIR}/openimageio)
                        set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include)
                        set(OPENIMAGEIO_LIBRARIES OpenImageIO)
-                       set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib)
+                       set_lib_path(OPENIMAGEIO_LIBPATH "openimageio/lib")
                        set(OPENIMAGEIO_DEFINITIONS)
                endif()
 
@@ -1431,11 +1427,9 @@ endif()
 if(MSVC10)
        if(WITH_IMAGE_OPENEXR)
                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()
        if(WITH_OPENCOLLADA)
                message(WARNING "MSVC 2010 does not support OpenCollada, disabling WITH_OPENCOLLADA. To enable support use Use MSVC 2008")
-               set(WITH_OPENCOLLADA OFF)
        endif()
 endif()
 
@@ -1577,6 +1571,7 @@ if(FIRST_RUN)
 
        info_cfg_text("Modifiers:")
        info_cfg_option(WITH_MOD_BOOLEAN)
+       info_cfg_option(WITH_MOD_REMESH)
        info_cfg_option(WITH_MOD_DECIMATE)
        info_cfg_option(WITH_MOD_FLUID)
        info_cfg_option(WITH_MOD_OCEANSIM)
index 88444c6131485020679b5db7182bc6e8ae7b6953..ee43015cf6ec1897ee2bc77f4284b6c4fd8dfb76 100644 (file)
@@ -264,6 +264,7 @@ if 'blenderlite' in B.targets:
     target_env_defs['WITH_BF_OCEANSIM'] = False
     target_env_defs['WITH_BF_DECIMATE'] = 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_3DMOUSE'] = False
     
index c6a834050d04fd563e1bef3b7a8b5abe3dfe1b74..406f2537dce748b622f243394cf99f24f20f35a8 100644 (file)
@@ -665,3 +665,16 @@ function(delayed_do_install
        endif()
 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()
\ No newline at end of file
index d9fafbda5b04d3e9cc0c9894683402a4a3392a80..e4f8827b7c82fe63f9916226b723d2c4073589ee 100644 (file)
@@ -156,15 +156,15 @@ WITH_BF_CYCLES = True
 
 WITH_BF_OIIO = True
 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_LIBPATH = '#../lib/windows/gcc/openimageio/lib'
+BF_OIIO_LIBPATH = BF_OIIO + '/lib'
 
 WITH_BF_BOOST = True
 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_LIBPATH = '#../lib/windows/boost/lib/gcc'
+BF_BOOST_LIBPATH = BF_BOOST + '/lib/gcc'
 
 #Ray trace optimization
 WITH_BF_RAYOPTIMIZATION = True
index adeca5668eb68c047f4d3375ddc4c1816ccabbeb..9d47edcfd793257e31566f9892a10749eb354d7c 100644 (file)
@@ -152,6 +152,7 @@ def validate_arguments(args, bc):
             'WITH_BF_FLUID',
             'WITH_BF_DECIMATE',
             'WITH_BF_BOOLEAN',
+            'WITH_BF_REMESH',
             'WITH_BF_OCEANSIM',
             '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',
@@ -261,6 +262,7 @@ def read_opts(env, cfg, args):
         (BoolVariable('WITH_BF_FLUID', 'Build with Fluid simulation (Elbeem)', True)),
         (BoolVariable('WITH_BF_DECIMATE', 'Build with decimate 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)),
         ('BF_PROFILE_FLAGS', 'Profiling compiler flags', ''),
         (BoolVariable('WITH_BF_OPENAL', 'Use OpenAL if true', False)),
index a5dd3b168607b4b10b376a0e66fe9701307f4711..60253e08d4c1847ce982ca2fc148f341778cb45a 100644 (file)
@@ -45,7 +45,7 @@ if(WITH_BUILTIN_GLEW)
 endif()
 
 if(WITH_GAMEENGINE)
-   add_subdirectory(recastnavigation)
+       add_subdirectory(recastnavigation)
 endif()
 
 if(WITH_IMAGE_OPENJPEG AND (NOT UNIX OR APPLE))
index 0f7672595d75058c99bcdbae220a06b2ef144b6b..9f5217e68e3098e005a11db33609f7bf62fb4f57 100644 (file)
@@ -36,6 +36,10 @@ if(WITH_AUDASPACE)
        add_subdirectory(audaspace)
 endif()
 
+if(WITH_MOD_REMESH)
+       add_subdirectory(dualcon)
+endif()
+
 if(WITH_MOD_FLUID)
        add_subdirectory(elbeem)
 endif()
index c13714543cbeee9518c5bd88023a8898036948eb..bb19426263a7ff19be0483d9221e967cc7a08c7a 100644 (file)
@@ -22,6 +22,9 @@ SConscript(['audaspace/SConscript',
 # perhaps get rid of intern/csg?
 NEW_CSG='false'
 
+if env ['WITH_BF_REMESH']:
+       SConscript(['dualcon/SConscript'])
+
 if env['WITH_BF_FLUID']:
     SConscript(['elbeem/SConscript'])
     
index 9a79c412e4ff244c521cdc596e19746db7e28913..543e7e087b11a74d9940ca0621c045c68a0d813c 100644 (file)
@@ -202,7 +202,7 @@ Operate(
 }
 
 
-       void 
+       void
 BSP_GhostTestApp3D::
 UpdateFrame(
 ){
@@ -210,9 +210,9 @@ if (m_window) {
 
        GHOST_Rect v_rect;
        m_window->getClientBounds(v_rect);
-       
+
        glViewport(0,0,v_rect.getWidth(),v_rect.getHeight());
-       
+
 }
 }
 
index 3dc9ca5d284da360dc6ee4a4c45c8ed67b9d9292..114ff47663b8e6172984812099423225825571d6 100644 (file)
@@ -36,19 +36,19 @@ if(WITH_CYCLES_OPTIMIZED_KERNEL)
 endif()
 
 if(WITH_CYCLES_NETWORK)
-  add_definitions(-DWITH_NETWORK)
+       add_definitions(-DWITH_NETWORK)
 endif()
 
 if(WITH_CYCLES_OSL)
-  add_definitions(-DWITH_OSL)
+       add_definitions(-DWITH_OSL)
 endif()
 
 if(WITH_CYCLES_PARTIO)
-  add_definitions(-DWITH_PARTIO)
+       add_definitions(-DWITH_PARTIO)
 endif()
 
 if(WITH_CYCLES_CUDA_BINARIES)
-  add_definitions(-DWITH_CUDA_BINARIES)
+       add_definitions(-DWITH_CUDA_BINARIES)
 endif()
 
 add_definitions(-DWITH_OPENCL)
index 9777de14b1e98801c8572fa7cc596277bd3ef41a..cbc430d9240a800ae1253c48e313d4920d1137c1 100644 (file)
@@ -72,17 +72,12 @@ static float blender_camera_focal_distance(BL::Object b_ob, BL::Camera b_camera)
        if(!b_dof_object)
                return b_camera.dof_distance();
        
-       /* for dof object, return distance along camera direction. this is
-        * compatible with blender, but does it fit our dof model? */
-       Transform obmat = get_transform(b_ob.matrix_world());
+       /* for dof object, return distance along camera Z direction */
+       Transform obmat = transform_clear_scale(get_transform(b_ob.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);
-       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);
+       return fabsf(transform_get_column(&mat, 3).z);
 }
 
 static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob)
index 5c39a3f169d132677f97a0b3df59672510b0beac..f32d2d9a2ce1f367cec9752a7d3294570cff0f13 100644 (file)
@@ -597,10 +597,14 @@ static void add_nodes(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNodeTr
                else
                        to_pair = sockets_map[b_to_sock.ptr.data];
 
-               ShaderOutput *output = from_pair.first->output(from_pair.second.c_str());
-               ShaderInput *input = to_pair.first->input(to_pair.second.c_str());
+               /* either node may be NULL when the node was not exported, typically
+                  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);
+               }
        }
 }
 
index da776c8909e9efa4c650dc063512a3703b958136..8fd7a1612e88ad153fb2c8fc110e80aa5239ac51 100644 (file)
@@ -30,7 +30,8 @@ shader node_hsv(
        float t = clamp(Fac, 0.0, 1.0);
        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[1] *= Saturation;
        Color[2] *= Value;
index fc927f297f55b1b89d296824a4517ecfccf13504..ed17d3fc985ee7aa4cb6c7e1cb3d73c0b2c1ebae 100644 (file)
@@ -110,7 +110,8 @@ __device void svm_node_hsv(KernelGlobals *kg, ShaderData *sd, float *stack, uint
 
        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.y *= sat;
        color.z *= val;
index 0b3f63b6d7e7bc4fe3bde973f1b14d0f77f3de58..bed2a8d574d489f392d8871b03d5635654479b6b 100644 (file)
@@ -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 direction;
-       direction.x = node1.x;
-       direction.y = node1.y;
-       direction.z = node1.z;
+       direction.x = __int_as_float(node1.x);
+       direction.y = __int_as_float(node1.y);
+       direction.z = __int_as_float(node1.z);
        direction = normalize(direction);
 
        if (stack_valid(out_normal_offset))
diff --git a/intern/dualcon/CMakeLists.txt b/intern/dualcon/CMakeLists.txt
new file mode 100644 (file)
index 0000000..caa1ea0
--- /dev/null
@@ -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}" "")
+
diff --git a/intern/dualcon/SConscript b/intern/dualcon/SConscript
new file mode 100644 (file)
index 0000000..481e9ae
--- /dev/null
@@ -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] )
diff --git a/intern/dualcon/dualcon.h b/intern/dualcon/dualcon.h
new file mode 100644 (file)
index 0000000..9346adc
--- /dev/null
@@ -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
diff --git a/intern/dualcon/intern/GeoCommon.h b/intern/dualcon/intern/GeoCommon.h
new file mode 100644 (file)
index 0000000..3b2789b
--- /dev/null
@@ -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
diff --git a/intern/dualcon/intern/MemoryAllocator.h b/intern/dualcon/intern/MemoryAllocator.h
new file mode 100644 (file)
index 0000000..de9dca1
--- /dev/null
@@ -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
diff --git a/intern/dualcon/intern/ModelReader.h b/intern/dualcon/intern/ModelReader.h
new file mode 100644 (file)
index 0000000..e70a158
--- /dev/null
@@ -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
diff --git a/intern/dualcon/intern/Projections.cpp b/intern/dualcon/intern/Projections.cpp
new file mode 100644 (file)
index 0000000..1f0831c
--- /dev/null
@@ -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}
+};
diff --git a/intern/dualcon/intern/Projections.h b/intern/dualcon/intern/Projections.h
new file mode 100644 (file)
index 0000000..2495747
--- /dev/null
@@ -0,0 +1,844 @@
+/*
+ * ***** 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(FREE_WINDOWS)
+#define LONG __int64
+#else
+#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
diff --git a/intern/dualcon/intern/Queue.h b/intern/dualcon/intern/Queue.h
new file mode 100644 (file)
index 0000000..61d7e2a
--- /dev/null
@@ -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
diff --git a/intern/dualcon/intern/cubes.h b/intern/dualcon/intern/cubes.h
new file mode 100644 (file)
index 0000000..0cdd791
--- /dev/null
@@ -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
diff --git a/intern/dualcon/intern/dualcon_c_api.cpp b/intern/dualcon/intern/dualcon_c_api.cpp
new file mode 100644 (file)
index 0000000..d710ada
--- /dev/null
@@ -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();
+}
diff --git a/intern/dualcon/intern/manifold_table.cpp b/intern/dualcon/intern/manifold_table.cpp
new file mode 100644 (file)
index 0000000..cebf389
--- /dev/null
@@ -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}}}
+};
diff --git a/intern/dualcon/intern/manifold_table.h b/intern/dualcon/intern/manifold_table.h
new file mode 100644 (file)
index 0000000..1827623
--- /dev/null
@@ -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
diff --git a/intern/dualcon/intern/marching_cubes_table.cpp b/intern/dualcon/intern/marching_cubes_table.cpp
new file mode 100644 (file)
index 0000000..4c78108
--- /dev/null
@@ -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}}
+};
diff --git a/intern/dualcon/intern/marching_cubes_table.h b/intern/dualcon/intern/marching_cubes_table.h
new file mode 100644 (file)
index 0000000..e45e1c6
--- /dev/null
@@ -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
diff --git a/intern/dualcon/intern/octree.cpp b/intern/dualcon/intern/octree.cpp
new file mode 100644 (file)
index 0000000..90dbf53
--- /dev/null
@@ -0,0 +1,4311 @@
+/*
+ * ***** 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 "octree.h"
+#include <Eigen/Dense>
+#include <limits>
+#include <time.h>
+
+/**
+ * Implementations of Octree member functions.
+ *
+ * @author Tao Ju
+ */
+
+/* set to non-zero value to enable debugging output */
+#define DC_DEBUG 0
+
+#if DC_DEBUG
+/* enable debug printfs */
+#define dc_printf printf
+#else
+/* disable debug printfs */
+#define dc_printf(...) do {} while(0)
+#endif
+
+Octree::Octree( ModelReader* mr,
+                               DualConAllocOutput alloc_output_func,
+                               DualConAddVert add_vert_func,
+                               DualConAddQuad add_quad_func,
+                               DualConFlags flags, DualConMode dualcon_mode, int depth,
+                               float threshold, float sharpness )
+       : use_flood_fill(flags & DUALCON_FLOOD_FILL),
+         /* note on `use_manifold':
+                
+                After playing around with this option, the only case I could
+                find where this option gives different results is on
+                relatively thin corners. Sometimes along these corners two
+                vertices from seperate sides will be placed in the same
+                position, so hole gets filled with a 5-sided face, where two
+                of those vertices are in the same 3D location. If
+                `use_manifold' is disabled, then the modifier doesn't
+                generate two separate vertices so the results end up as all
+                quads.
+
+                Since the results are just as good with all quads, there
+                doesn't seem any reason to allow this to be toggled in
+                Blender. -nicholasbishop
+          */
+         use_manifold(false),
+         hermite_num(sharpness),
+         mode(dualcon_mode),
+         alloc_output(alloc_output_func),
+         add_vert(add_vert_func),
+         add_quad(add_quad_func)
+{
+       this->thresh = threshold ;
+       this->reader = mr ;
+       this->dimen = 1 << GRID_DIMENSION ;
+       this->range = reader->getBoundingBox( this->origin ) ;
+       this->nodeCount = this->nodeSpace = 0;
+       this->maxDepth = depth ;
+       this->mindimen = ( dimen >> maxDepth ) ;
+       this->minshift = ( GRID_DIMENSION - maxDepth ) ;
+       this->buildTable( ) ;
+
+       flood_bytes = use_flood_fill ? FLOOD_FILL_BYTES : 0;
+       leaf_extra_bytes = flood_bytes + CINDY_BYTES;
+
+#ifdef USE_HERMIT
+       leaf_node_bytes = 7 + leaf_extra_bytes;
+#else
+       leaf_node_bytes = 3 + leaf_extra_bytes;
+#endif
+
+#ifdef QIANYI
+       dc_printf("Origin: (%f %f %f), Dimension: %f\n", origin[0], origin[1], origin[2], range) ;
+#endif
+
+       this->maxTrianglePerCell = 0 ;
+
+       // Initialize memory
+#ifdef IN_VERBOSE_MODE
+       dc_printf("Range: %f origin: %f, %f,%f \n", range, origin[0], origin[1], origin[2] ) ;
+       dc_printf("Initialize memory...\n") ;
+#endif
+       initMemory( ) ;
+       this->root = createInternal( 0 ) ;
+
+       // Read MC table
+#ifdef IN_VERBOSE_MODE
+       dc_printf("Reading contour table...\n") ;
+#endif
+       this->cubes = new Cubes();
+
+}
+
+Octree::~Octree( )
+{
+       freeMemory( ) ;
+}
+
+void Octree::scanConvert()
+{
+       // Scan triangles
+#if DC_DEBUG
+       clock_t start, finish ;
+       start = clock( ) ;
+#endif
+       
+       this->addTrian( ) ;
+       this->resetMinimalEdges( ) ;
+       this->preparePrimalEdgesMask( this->root ) ;
+
+#if DC_DEBUG
+       finish = clock( ) ;
+       dc_printf("Time taken: %f seconds                   \n", 
+               (double)(finish - start) / CLOCKS_PER_SEC ) ;
+#endif
+
+       // Generate signs
+       // Find holes
+#if DC_DEBUG
+       dc_printf("Patching...\n") ;
+       start = clock( ) ;
+#endif
+       this->trace( ) ;
+#if DC_DEBUG
+       finish = clock( ) ;
+       dc_printf("Time taken: %f seconds \n",  (double)(finish - start) / CLOCKS_PER_SEC ) ;
+#ifdef IN_VERBOSE_MODE
+       dc_printf("Holes: %d Average Length: %f Max Length: %d \n", numRings, (float)totRingLengths / (float) numRings, maxRingLength ) ;
+#endif
+#endif
+       
+       // Check again
+       int tnumRings = numRings ;
+       this->trace( ) ;
+#ifdef IN_VERBOSE_MODE
+       dc_printf("Holes after patching: %d \n", numRings) ;
+#endif 
+       numRings = tnumRings ;
+
+#if DC_DEBUG
+       dc_printf("Building signs...\n") ;
+       start = clock( ) ;
+#endif
+       this->buildSigns( ) ;
+#if DC_DEBUG
+       finish = clock( ) ;
+       dc_printf("Time taken: %f seconds \n",  (double)(finish - start) / CLOCKS_PER_SEC ) ;
+#endif
+
+       if(use_flood_fill) {
+               /*
+                 start = clock( ) ;
+                 this->floodFill( ) ;
+                 // Check again
+                 tnumRings = numRings ;
+                 this->trace( ) ;
+                 dc_printf("Holes after filling: %d \n", numRings) ;
+                 numRings = tnumRings ;
+                 this->buildSigns( ) ;
+                 finish = clock( ) ;
+                 dc_printf("Time taken: %f seconds \n",        (double)(finish - start) / CLOCKS_PER_SEC ) ;
+               */
+#if DC_DEBUG
+               start = clock( ) ;
+               dc_printf("Removing components...\n");
+#endif
+               this->floodFill( ) ;
+               this->buildSigns( ) ;
+               //      dc_printf("Checking...\n");
+               //      this->floodFill( ) ;
+#if DC_DEBUG
+               finish = clock( ) ;
+               dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC ) ;
+#endif
+       }
+
+       // Output
+#ifdef OUTPUT_REPAIRED
+#if DC_DEBUG
+       start = clock( ) ;
+#endif
+       writeOut();
+#if DC_DEBUG
+       finish = clock( ) ;
+#endif
+       // dc_printf("Time taken: %f seconds \n",       (double)(finish - start) / CLOCKS_PER_SEC ) ;
+#ifdef CINDY
+       this->writeTags( "tags.txt" ) ;
+       dc_printf("Tags output to tags.txt\n") ;
+#endif
+
+#endif
+
+       // Print info
+#ifdef IN_VERBOSE_MODE
+       printMemUsage( ) ;
+#endif
+}
+
+#if 0
+void Octree::writeOut( char* fname )
+{
+       dc_printf( "\n" ) ;
+       if ( strstr( fname, ".ply" ) != NULL )
+       {
+               dc_printf("Writing PLY file format.\n") ;
+               this->outType = 1 ;
+               writePLY( fname ) ;
+       } 
+       else if ( strstr( fname, ".off" ) != NULL )
+       {
+               dc_printf("Writing OFF file format.\n") ;
+               this->outType = 0 ;
+               writeOFF( fname ) ;
+       }
+       else if ( strstr( fname, ".sof" ) != NULL )
+       {
+               dc_printf("Writing Signed Octree File format.\n") ;
+               this->outType = 2 ;
+               writeOctree( fname ) ;
+       }
+       else if ( strstr( fname, ".dcf" ) != NULL )
+       {
+#ifdef USE_HERMIT
+               dc_printf("Writing Dual Contouring File format.\n") ;
+               this->outType = 3 ;
+               writeDCF( fname ) ;
+#else
+               dc_printf("Can not write Dual Contouring File format in non-DC mode.\n") ;
+#endif
+       }
+#ifdef USE_HERMIT
+       else if ( strstr( fname, ".sog" ) != NULL )
+       {
+               dc_printf("Writing signed octree with geometry.\n") ;
+               this->outType = 4 ;
+               writeOctreeGeom( fname ) ;
+       }
+#endif
+       /*
+       else if ( strstr( fname, ".sof" ) != NULL )
+       {
+               dc_printf("Writing SOF file format.\n") ;
+               this->outType = 2 ;
+               writeOctree( fname ) ;
+       }
+       */
+       else
+       {
+               dc_printf("Unknown output format.\n") ;
+       }
+
+}
+#endif
+
+void Octree::initMemory( )
+{
+#ifdef USE_HERMIT
+       const int leaf_node_bytes = 7;
+#else
+       const int leaf_node_bytes = 3;
+#endif
+
+       if(use_flood_fill) {
+               const int bytes = leaf_node_bytes + CINDY_BYTES + FLOOD_FILL_BYTES;
+               this->leafalloc[ 0 ] = new MemoryAllocator< bytes > ( ) ;
+               this->leafalloc[ 1 ] = new MemoryAllocator< bytes + EDGE_BYTES > ( ) ;
+               this->leafalloc[ 2 ] = new MemoryAllocator< bytes + EDGE_BYTES * 2 > ( ) ;
+               this->leafalloc[ 3 ] = new MemoryAllocator< bytes + EDGE_BYTES * 3 > ( ) ;
+       }
+       else {
+               const int bytes = leaf_node_bytes + CINDY_BYTES;
+               this->leafalloc[ 0 ] = new MemoryAllocator< bytes > ( ) ;
+               this->leafalloc[ 1 ] = new MemoryAllocator< bytes + EDGE_BYTES > ( ) ;
+               this->leafalloc[ 2 ] = new MemoryAllocator< bytes + EDGE_BYTES * 2 > ( ) ;
+               this->leafalloc[ 3 ] = new MemoryAllocator< bytes + EDGE_BYTES * 3 > ( ) ;
+       }
+
+       this->alloc[ 0 ] = new MemoryAllocator< INTERNAL_NODE_BYTES > ( ) ;
+       this->alloc[ 1 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES > ( ) ;
+       this->alloc[ 2 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*2 > ( ) ;
+       this->alloc[ 3 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*3 > ( ) ;
+       this->alloc[ 4 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*4 > ( ) ;
+       this->alloc[ 5 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*5 > ( ) ;
+       this->alloc[ 6 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*6 > ( ) ;
+       this->alloc[ 7 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*7 > ( ) ;
+       this->alloc[ 8 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*8 > ( ) ;
+}
+
+void Octree::freeMemory( )
+{
+       for ( int i = 0 ; i < 9 ; i ++ )
+       {
+               alloc[i]->destroy() ;
+               delete alloc[i] ;
+       }
+
+       for ( int i = 0 ; i < 4 ; i ++ )
+       {
+               leafalloc[i]->destroy() ;
+               delete leafalloc[i] ;
+       }
+}
+
+void Octree::printMemUsage( )
+{
+       int totalbytes = 0 ;
+       dc_printf("********* Internal nodes: \n") ;
+       for ( int i = 0 ; i < 9 ; i ++ )
+       {
+               this->alloc[ i ]->printInfo() ;
+
+               totalbytes += alloc[i]->getAll( ) * alloc[i]->getBytes() ;
+       }
+       dc_printf("********* Leaf nodes: \n") ;
+       int totalLeafs = 0 ;
+       for ( int i = 0 ; i < 4 ; i ++ )
+       {
+               this->leafalloc[ i ]->printInfo() ;
+
+               totalbytes += leafalloc[i]->getAll( ) * leafalloc[i]->getBytes() ;
+               totalLeafs += leafalloc[i]->getAllocated() ;
+       }
+       
+       dc_printf("Total allocated bytes on disk: %d \n", totalbytes) ;
+       dc_printf("Total leaf nodes: %d\n", totalLeafs ) ;
+}
+
+void Octree::resetMinimalEdges( )
+{
+       this->cellProcParity( this->root, 0, maxDepth ) ;
+}
+
+void Octree::writeModel( char* fname )
+{
+       reader->reset() ;
+
+       int nFace = reader->getNumTriangles() ;
+       Triangle* trian ;
+       // int unitcount = 10000;
+       int count = 0 ;
+       int nVert = nFace * 3 ;
+       FILE* modelfout = fopen( "model.off", "w" ) ;
+       fprintf( modelfout, "OFF\n" ) ;
+       fprintf( modelfout, "%d %d 0\n", nVert, nFace ) ;
+
+       //int total = this->reader->getNumTriangles() ;
+       dc_printf( "Start writing model to OFF...\n" ) ;
+       srand(0) ;
+       while ( ( trian = reader->getNextTriangle() ) != NULL )
+       {
+               // Drop polygons
+               {
+                       int i, j ;
+
+                       // Blow up the triangle
+                       float mid[3] = {0, 0, 0} ;
+                       for ( i = 0 ; i < 3 ; i ++ )
+                               for ( j = 0 ; j < 3 ; j ++ )
+                               {
+                                       trian->vt[i][j] = dimen * ( trian->vt[i][j] - origin[j] ) / range ;
+
+                                       mid[j] += trian->vt[i][j] / 3 ;
+                               }
+                               
+                               // Generate projections
+                               // LONG cube[2][3] = { { 0, 0, 0 }, { dimen, dimen, dimen } } ;
+                               int trig[3][3] ;
+
+                               // Blowing up the triangle to the grid
+                               for ( i = 0 ; i < 3 ; i ++ )
+                                       for (  j = 0 ; j < 3 ; j ++ )
+                                       {
+                                               trig[i][j] = (int) (trian->vt[i][j]) ;
+                                               // Perturb end points, if set so
+                                       }
+
+                                       
+                                       for ( i = 0 ; i < 3 ; i ++ )
+                                       {
+                                               fprintf( modelfout, "%f %f %f\n", 
+                                                       (float)(((double) trig[i][0] / dimen) * range  + origin[0]) ,
+                                                       (float)(((double) trig[i][1] / dimen) * range  + origin[1]) ,
+                                                       (float)(((double) trig[i][2] / dimen) * range  + origin[2]) ) ;
+                                       }
+               }
+               delete trian ;
+
+               count ++ ;
+               
+       }
+
+       for ( int i = 0 ; i < nFace ; i ++ )
+       {
+               fprintf( modelfout, "3 %d %d %d\n", 3 * i + 2, 3 * i + 1, 3 * i  ) ;
+       }
+
+       fclose( modelfout ) ;
+
+}
+
+#ifdef CINDY
+void Octree::writeTags( char* fname )
+{
+       FILE* fout = fopen( fname, "w" ) ;
+
+       clearCindyBits( root, maxDepth ) ;
+       readVertices() ;
+       outputTags( root, maxDepth, fout ) ;
+
+       fclose ( fout ) ;
+}
+
+void Octree::readVertices( )
+{
+       int total = this->reader->getNumVertices() ;
+       reader->reset() ;
+       float v[3] ;
+       int st[3] = {0,0,0};
+       int unitcount = 1000 ;
+       dc_printf( "\nRead in original %d vertices...\n", total ) ;
+
+       for ( int i = 0 ; i < total ; i ++ )
+       {
+               reader->getNextVertex( v ) ;
+               // Blowing up the triangle to the grid
+               float mid[3] = {0, 0, 0} ;
+               for ( int j = 0 ; j < 3 ; j ++ )
+               {
+                       v[j] = dimen * ( v[j] - origin[j] ) / range ;
+               }
+
+//             dc_printf("vertex: %f %f %f, dimen: %d\n", v[0], v[1], v[2], dimen ) ;
+               readVertex ( root, st, dimen, maxDepth, v, i ) ;
+
+               
+               if ( i % unitcount == 0 )
+               {
+                       putchar ( 13 ) ;
+
+                       switch ( ( i / unitcount ) % 4 )
+                       {
+                       case 0 : dc_printf("-");
+                               break ;
+                       case 1 : dc_printf("/") ;
+                               break ;
+                       case 2 : dc_printf("|");
+                               break ;
+                       case 3 : dc_printf("\\") ;
+                               break ;
+                       }
+
+                       float percent = (float) i / total ;
+                       /*
+                       int totbars = 50 ;
+                       int bars = (int)( percent * totbars ) ;
+                       for ( int i = 0 ; i < bars ; i ++ )
+                       {
+                               putchar( 219 ) ;
+                       }
+                       for ( i = bars ; i < totbars ; i ++ )
+                       {
+                               putchar( 176 ) ;
+                       }
+                       */
+
+                       dc_printf(" %d vertices: ", i ) ;
+                       dc_printf( " %f%% complete.", 100 * percent ) ;
+               }
+               
+       }
+       putchar ( 13 ) ;
+       dc_printf("                                             \n");
+}
+
+void Octree::readVertex(  UCHAR* node, int st[3], int len, int height, float v[3], int index )
+{
+       int nst[3] ;
+       nst[0] = ( (int) v[0] / mindimen ) * mindimen ;
+       nst[1] = ( (int) v[1] / mindimen ) * mindimen ;
+       nst[2] = ( (int) v[2] / mindimen ) * mindimen ;
+
+       UCHAR* cell = this->locateLeafCheck( nst ) ;
+       if ( cell == NULL )
+       {
+               dc_printf("Cell %d %d %d is not found!\n", nst[0]/ mindimen, nst[1]/ mindimen, nst[2]/ mindimen) ;
+               return ;
+       }
+
+       setOriginalIndex( cell, index ) ;
+
+
+       /*
+       int i ;
+       if ( height == 0 )
+       {
+               // Leaf cell, assign index
+               dc_printf("Setting: %d\n", index ) ;
+               setOriginalIndex( node, index ) ;
+       }
+       else
+       {
+               len >>= 1 ;
+               // Internal cell, check and recur
+               int x = ( v[0] > st[0] + len ) ? 1 : 0 ;
+               int y = ( v[1] > st[1] + len ) ? 1 : 0 ;
+               int z = ( v[2] > st[2] + len ) ? 1 : 0 ;
+               int child = x * 4 + y * 2 + z ;
+
+               int count = 0 ;
+               for ( i = 0 ; i < 8 ; i ++ )
+               {
+                       if ( i == child && hasChild( node, i ) )
+                       {
+                               int nst[3] ;
+                               nst[0] = st[0] + vertmap[i][0] * len ;
+                               nst[1] = st[1] + vertmap[i][1] * len ;
+                               nst[2] = st[2] + vertmap[i][2] * len ;
+
+                               dc_printf("Depth: %d -- child %d vertex: %f %f %f in %f %f %f\n", height - 1, child, v[0]/mindimen, v[1]/mindimen, v[2]/mindimen, 
+                                       nst[0]/mindimen, nst[1]/mindimen, nst[2]/mindimen, len/mindimen ) ;
+                               
+                               readVertex( getChild( node, count ), nst, len, height - 1, v, index ) ;
+                               count ++ ;
+                       }
+               }
+       }
+       */
+}
+
+void Octree::outputTags( UCHAR* node, int height, FILE* fout )
+{
+       int i ;
+
+       if ( height == 0 )
+       {
+               // Leaf cell, generate
+               int smask = getSignMask( node ) ;
+
+               if(use_manifold) {
+                       int comps = manifold_table[ smask ].comps ;
+                       if ( comps != 1 )
+                       {
+                               return ;
+                       }
+               }
+               else
+               {
+                       if ( smask == 0 || smask == 255 )
+                       {
+                               return ;
+                       }
+               }
+
+               int rindex = getMinimizerIndex( node ) ;
+               int oindex = getOriginalIndex( node ) ;
+
+               if ( oindex >= 0 )
+               {
+                       fprintf( fout, "%d: %d\n", rindex, oindex ) ;
+               }
+
+       }
+       else
+       {
+               // Internal cell, recur
+               int count = 0 ;
+               for ( i = 0 ; i < 8 ; i ++ )
+               {
+                       if ( hasChild( node, i ) )
+                       {
+                               outputTags( getChild( node, count ), height - 1, fout ) ;
+                               count ++ ;
+                       }
+               }
+       }
+}
+
+void Octree::clearCindyBits( UCHAR* node, int height )
+{
+       int i;
+
+       if ( height == 0 )
+       {
+               // Leaf cell, 
+               {
+                       setOriginalIndex( node, - 1 ) ;
+               }
+       }
+       else
+       {
+               // Internal cell, recur
+               int count = 0 ;
+               for ( i = 0 ; i < 8 ; i ++ )
+               {
+                       if ( hasChild( node, i ) )
+                       {
+                               clearCindyBits( getChild( node, count ), height - 1 ) ;
+                               count ++ ;
+                       }
+               }
+       }       
+}
+#endif
+
+void Octree::addTrian( )
+{
+       Triangle* trian ;
+       int count = 0 ;
+       
+#if DC_DEBUG
+       int total = this->reader->getNumTriangles() ;
+       int unitcount = 1000 ;
+       dc_printf( "\nScan converting to depth %d...\n", maxDepth ) ;
+#endif
+
+       srand(0) ;
+
+       while ( ( trian = reader->getNextTriangle() ) != NULL )
+       {
+               // Drop triangles
+               {
+                       addTrian ( trian, count ) ;
+               }
+               delete trian ;
+
+               count ++ ;
+
+#if DC_DEBUG
+               if ( count % unitcount == 0 )
+               {
+                       putchar ( 13 ) ;
+
+                       switch ( ( count / unitcount ) % 4 )
+                       {
+                       case 0 : dc_printf("-");
+                               break ;
+                       case 1 : dc_printf("/") ;
+                               break ;
+                       case 2 : dc_printf("|");
+                               break ;
+                       case 3 : dc_printf("\\") ;
+                               break ;
+                       }
+
+                       float percent = (float) count / total ;
+                       
+                       /*
+                       int totbars = 50 ;
+                       int bars = (int)( percent * totbars ) ;
+                       for ( int i = 0 ; i < bars ; i ++ )
+                       {
+                               putchar( 219 ) ;
+                       }
+                       for ( i = bars ; i < totbars ; i ++ )
+                       {
+                               putchar( 176 ) ;
+                       }
+                       */
+
+                       dc_printf(" %d triangles: ", count ) ;
+                       dc_printf( " %f%% complete.", 100 * percent ) ;
+               }
+#endif
+               
+       }
+       putchar ( 13 ) ;
+}
+
+void Octree::addTrian( Triangle* trian, int triind )
+{
+       int i, j ;
+
+       // Blowing up the triangle to the grid
+       float mid[3] = {0, 0, 0} ;
+       for ( i = 0 ; i < 3 ; i ++ )
+               for ( j = 0 ; j < 3 ; j ++ )
+               {
+                       trian->vt[i][j] = dimen * ( trian->vt[i][j] - origin[j] ) / range ;
+                       mid[j] += trian->vt[i][j] / 3 ;
+               }
+
+       // Generate projections
+       LONG cube[2][3] = { { 0, 0, 0 }, { dimen, dimen, dimen } } ;
+       LONG trig[3][3] ;
+       
+       for ( i = 0 ; i < 3 ; i ++ )
+               for (  j = 0 ; j < 3 ; j ++ )
+               {
+                       trig[i][j] = (LONG) (trian->vt[i][j]) ;
+       // Perturb end points, if set so
+               }
+               
+       // Add to the octree
+       // int start[3] = { 0, 0, 0 } ;
+       LONG errorvec = (LONG) ( 0 ) ;
+       Projections* proj = new Projections( cube, trig, errorvec, triind ) ;
+       root = addTrian( root, proj, maxDepth ) ;
+       
+       delete proj->inherit ;
+       delete proj ;
+}
+
+
+UCHAR* Octree::addTrian( UCHAR* node, Projections* p, int height )
+{
+       int i ;
+       int vertdiff[8][3] = {{0,0,0},{0,0,1},{0,1,-1},{0,0,1},{1,-1,-1},{0,0,1},{0,1,-1},{0,0,1}} ;
+       UCHAR boxmask = p->getBoxMask( ) ;
+       Projections* subp = new Projections( p ) ;
+       
+       int count = 0 ;
+       int tempdiff[3] = {0,0,0} ;
+       for ( i = 0 ; i < 8 ; i ++ )
+       {
+               tempdiff[0] += vertdiff[i][0] ;
+               tempdiff[1] += vertdiff[i][1] ;
+               tempdiff[2] += vertdiff[i][2] ;
+
+               /* Quick pruning using bounding box */
+               if ( boxmask & ( 1 << i ) ) 
+               {
+                       subp->shift( tempdiff ) ;
+                       tempdiff[0] = tempdiff[1] = tempdiff[2] = 0 ;
+
+                       /* Pruning using intersection test */
+                       if ( subp->isIntersecting() )
+                       // if ( subp->getIntersectionMasks( cedgemask, edgemask ) )
+                       {
+                               if ( ! hasChild( node, i ) )
+                               {
+                                       if ( height == 1 )
+                                       {
+                                               node = addLeafChild( node, i, count, createLeaf(0) ) ;
+                                       }
+                                       else
+                                       {
+                                               node = addInternalChild( node, i, count, createInternal(0) ) ;
+                                       }
+                               }
+                               UCHAR* chd = getChild( node, count ) ;
+                                               
+                               if ( ! isLeaf( node, i ) )
+                               {
+                                       // setChild( node, count, addTrian ( chd, subp, height - 1, vertmask[i], edgemask ) ) ;
+                                       setChild( node, count, addTrian ( chd, subp, height - 1 ) ) ;
+                               }
+                               else
+                               {
+                                       setChild( node, count, updateCell( chd, subp ) ) ;
+                               }
+                       }
+               }
+
+               if ( hasChild( node, i ) )
+               {
+                       count ++ ;
+               }
+       }
+
+       delete subp ;
+       return node ;
+}
+
+UCHAR* Octree::updateCell( UCHAR* node, Projections* p )
+{
+       int i ;
+
+       // Edge connectivity
+       int mask[3] = { 0, 4, 8 } ;
+       int oldc = 0, newc = 0 ;
+       float offs[3] ;
+#ifdef USE_HERMIT
+       float a[3], b[3], c[3] ;
+#endif
+
+       for ( i = 0 ; i < 3 ; i ++ )
+       {
+               if ( ! getEdgeParity( node, mask[i] ) )
+               {
+                       if ( p->isIntersectingPrimary( i ) )
+                       {
+                               // this->actualQuads ++ ;
+                               setEdge( node, mask[i] ) ;
+                               offs[ newc ] = p->getIntersectionPrimary( i ) ;
+#ifdef USE_HERMIT
+                               a[ newc ] = (float) p->inherit->norm[0] ;
+                               b[ newc ] = (float) p->inherit->norm[1] ;
+                               c[ newc ] = (float) p->inherit->norm[2] ;
+#endif
+                               newc ++ ;
+                       }
+               }
+               else
+               {
+#ifndef USE_HERMIT
+                       offs[ newc ] = getEdgeOffset( node, oldc ) ;
+#else
+                       offs[ newc ] = getEdgeOffsetNormal( node, oldc, a[ newc ], b[ newc ], c[ newc ] ) ;
+#endif
+
+//                     if ( p->isIntersectingPrimary( i ) )
+                       {
+                               // dc_printf("Multiple intersections!\n") ;
+                               
+//                             setPatchEdge( node, i ) ;
+                       }
+                       
+                       oldc ++ ;
+                       newc ++ ;
+               }
+       }
+
+       if ( newc > oldc )
+       {
+               // New offsets added, update this node
+#ifndef USE_HERMIT
+               node = updateEdgeOffsets( node, oldc, newc, offs ) ;
+#else
+               node = updateEdgeOffsetsNormals( node, oldc, newc, offs, a, b, c ) ;
+#endif
+       }
+
+
+
+       return node ;
+}
+
+void Octree::preparePrimalEdgesMask( UCHAR* node )
+{
+       int count = 0 ;
+       for ( int i = 0 ; i < 8 ; i ++ )
+       {
+               if ( hasChild( node, i ) )
+               {
+                       if ( isLeaf( node, i ) )
+                       {
+                               createPrimalEdgesMask( getChild( node, count ) ) ;
+                       }
+                       else
+                       {
+                               preparePrimalEdgesMask( getChild( node, count ) ) ;
+                       }
+
+                       count ++ ;
+               }
+       }
+}
+
+void Octree::trace( )
+{
+       int st[3] = { 0, 0, 0, } ;
+       this->numRings = 0 ;
+       this->totRingLengths = 0 ;
+       this->maxRingLength = 0 ;
+
+       PathList* chdpath = NULL ;
+       this->root = trace( this->root, st, dimen, maxDepth, chdpath ) ;
+
+       if ( chdpath != NULL )
+       {
+               dc_printf("there are incomplete rings.\n") ;    
+               printPaths( chdpath ) ;
+       };
+}
+
+UCHAR* Octree::trace( UCHAR* node, int* st, int len, int depth, PathList*& paths)
+{
+       UCHAR* newnode = node ;
+       len >>= 1 ;
+       PathList* chdpaths[ 8 ] ;
+       UCHAR* chd[ 8 ] ;
+       int nst[ 8 ][ 3 ] ;
+       int i, j ;
+
+       // Get children paths
+       int chdleaf[ 8 ] ;
+       fillChildren( newnode, chd, chdleaf ) ;
+
+       // int count = 0 ;
+       for ( i = 0 ; i < 8 ; i ++ )
+       {
+               for ( j = 0 ; j < 3 ; j ++ )
+               {
+                       nst[ i ][ j ] = st[ j ] + len * vertmap[ i ][ j ] ;
+               }
+
+               if ( chd[ i ] == NULL || isLeaf( node, i ) )
+               {
+                       chdpaths[ i ] = NULL ;
+               }
+               else
+               {
+                       trace( chd[ i ], nst[i], len, depth - 1, chdpaths[ i ] ) ;
+               }
+       }
+
+       // Get connectors on the faces
+       PathList* conn[ 12 ] ;
+       UCHAR* nf[2] ;
+       int lf[2] ;
+       int df[2] = { depth - 1, depth - 1 } ;
+       int* nstf[ 2 ];
+
+       fillChildren( newnode, chd, chdleaf ) ;
+
+       for ( i = 0 ; i < 12 ; i ++ )
+       {
+               int c[ 2 ] = { cellProcFaceMask[ i ][ 0 ], cellProcFaceMask[ i ][ 1 ] };
+               
+               for ( int j = 0 ; j < 2 ; j ++ )
+               {
+                       lf[j] = chdleaf[ c[j] ] ;
+                       nf[j] = chd[ c[j] ] ;
+                       nstf[j] = nst[ c[j] ] ;
+               }
+
+               conn[ i ] = NULL ;
+               
+               findPaths( nf, lf, df, nstf, depth - 1, cellProcFaceMask[ i ][ 2 ], conn[ i ] ) ;
+
+               //if ( conn[i] )
+               //{
+               //              printPath( conn[i] ) ;
+               //}
+       }
+       
+       // Connect paths
+       PathList* rings = NULL ;
+       combinePaths( chdpaths[0], chdpaths[1], conn[8], rings ) ;
+       combinePaths( chdpaths[2], chdpaths[3], conn[9], rings ) ;
+       combinePaths( chdpaths[4], chdpaths[5], conn[10], rings ) ;
+       combinePaths( chdpaths[6], chdpaths[7], conn[11], rings ) ;
+
+       combinePaths( chdpaths[0], chdpaths[2], conn[4], rings ) ;
+       combinePaths( chdpaths[4], chdpaths[6], conn[5], rings ) ;
+       combinePaths( chdpaths[0], NULL, conn[6], rings ) ;
+       combinePaths( chdpaths[4], NULL, conn[7], rings ) ;
+
+       combinePaths( chdpaths[0], chdpaths[4], conn[0], rings ) ;
+       combinePaths( chdpaths[0], NULL, conn[1], rings ) ;
+       combinePaths( chdpaths[0], NULL, conn[2], rings ) ;
+       combinePaths( chdpaths[0], NULL, conn[3], rings ) ;
+
+       // By now, only chdpaths[0] and rings have contents
+
+       // Process rings
+       if ( rings )
+       {
+               // printPath( rings ) ;
+
+               /* Let's count first */
+               PathList* trings = rings ;
+               while ( trings )
+               {
+                       this->numRings ++ ;
+                       this->totRingLengths += trings->length ;
+                       if ( trings->length > this->maxRingLength )
+                       {
+                               this->maxRingLength = trings->length ;
+                       }
+                       trings = trings->next ;
+               }
+
+               // printPath( rings ) ;
+               newnode = patch( newnode, st, ( len << 1 ), rings ) ;
+       }
+
+       // Return incomplete paths
+       paths = chdpaths[0] ;
+       return newnode ;
+}
+
+void Octree::findPaths( UCHAR* node[2], int leaf[2], int depth[2], int* st[2], int maxdep, int dir, PathList*& paths )
+{
+       if ( ! ( node[0] && node[1] ) )
+       {
+               return ;
+       }
+
+       if ( ! ( leaf[0] && leaf[1] ) )
+       {
+               // Not at the bottom, recur
+
+               // Fill children nodes
+               int i, j ;
+               UCHAR* chd[ 2 ][ 8 ] ;
+               int chdleaf[ 2 ][ 8 ] ;
+               int nst[ 2 ][ 8 ][ 3 ] ;
+
+               for ( j = 0 ; j < 2 ; j ++ )
+               {
+                       if ( ! leaf[j] )
+                       {
+                               fillChildren( node[j], chd[j], chdleaf[j] ) ;
+
+                               int len = ( dimen >> ( maxDepth - depth[j] + 1 ) ) ;
+                               for ( i = 0 ; i < 8 ; i ++ )
+                               {
+                                       for ( int k = 0 ; k < 3 ; k ++ )
+                                       {
+                                               nst[ j ][ i ][ k ] = st[ j ][ k ] + len * vertmap[ i ][ k ] ;
+                                       }
+                               }
+
+                       }
+               }
+
+               // 4 face calls
+               UCHAR* nf[2] ;
+               int df[2] ;
+               int lf[2] ;
+               int* nstf[2] ;
+               for ( i = 0 ; i < 4 ; i ++ )
+               {
+                       int c[2] = { faceProcFaceMask[ dir ][ i ][ 0 ], faceProcFaceMask[ dir ][ i ][ 1 ] };
+                       for ( int j = 0 ; j < 2 ; j ++ )
+                       {
+                               if ( leaf[j] )
+                               {
+                                       lf[j] = leaf[j] ;
+                                       nf[j] = node[j] ;
+                                       df[j] = depth[j] ;
+                                       nstf[j] = st[j] ;
+                               }
+                               else
+                               {
+                                       lf[j] = chdleaf[ j ][ c[j] ] ;
+                                       nf[j] = chd[ j ][ c[j] ] ;
+                                       df[j] = depth[j] - 1 ;
+                                       nstf[j] = nst[ j ][ c[j] ] ;
+                               }
+                       }
+                       findPaths( nf, lf, df, nstf, maxdep - 1, faceProcFaceMask[ dir ][ i ][ 2 ], paths ) ;
+               }
+
+       }
+       else
+       {
+               // At the bottom, check this face
+               int ind = ( depth[0] == maxdep ? 0 : 1 ) ;
+               int fcind = 2 * dir + ( 1 - ind ) ;
+               if ( getFaceParity( node[ ind ], fcind ) )
+               {
+                       // Add into path
+                       PathElement* ele1 = new PathElement ;
+                       PathElement* ele2 = new PathElement ;
+
+                       ele1->pos[0] = st[0][0] ;
+                       ele1->pos[1] = st[0][1] ;
+                       ele1->pos[2] = st[0][2] ;
+
+                       ele2->pos[0] = st[1][0] ;
+                       ele2->pos[1] = st[1][1] ;
+                       ele2->pos[2] = st[1][2] ;
+
+                       ele1->next = ele2 ;
+                       ele2->next = NULL ;
+
+                       PathList* lst = new PathList ;
+                       lst->head = ele1 ;
+                       lst->tail = ele2 ;
+                       lst->length = 2 ;
+                       lst->next = paths ;
+                       paths = lst ;
+
+                       // int l = ( dimen >> maxDepth ) ;
+               }
+       }
+
+}
+
+void Octree::combinePaths( PathList*& list1, PathList* list2, PathList* paths, PathList*& rings )
+{
+       // Make new list of paths
+       PathList* nlist = NULL ;
+
+       // Search for each connectors in paths
+       PathList* tpaths = paths ;
+       PathList* tlist, * pre ;
+       while ( tpaths )
+       {
+               PathList* singlist = tpaths ;
+               PathList* templist ;
+               tpaths = tpaths->next ;
+               singlist->next = NULL ;
+
+               // Look for hookup in list1
+               tlist = list1 ;
+               pre = NULL ;
+               while ( tlist )
+               {
+                       if (  (templist = combineSinglePath( list1, pre, tlist, singlist, NULL, singlist )) != NULL )
+                       {
+                               singlist = templist ;
+                               continue ;
+                       }
+                       pre = tlist ;
+                       tlist = tlist->next ;
+               }
+
+               // Look for hookup in list2
+               tlist = list2 ;
+               pre = NULL ;
+               while ( tlist )
+               {
+                       if (  (templist = combineSinglePath( list2, pre, tlist, singlist, NULL, singlist )) != NULL )
+                       {
+                               singlist = templist ;
+                               continue ;
+                       }
+                       pre = tlist ;
+                       tlist = tlist->next ;
+               }
+
+               // Look for hookup in nlist
+               tlist = nlist ;
+               pre = NULL ;
+               while ( tlist )
+               {
+                       if (  (templist = combineSinglePath( nlist, pre, tlist, singlist, NULL, singlist )) != NULL )
+                       {
+                               singlist = templist ;
+                               continue ;
+                       }
+                       pre = tlist ;
+                       tlist = tlist->next ;
+               }
+
+               // Add to nlist or rings
+               if ( isEqual( singlist->head, singlist->tail ) )
+               {
+                       PathElement* temp = singlist->head ;
+                       singlist->head = temp->next ;
+                       delete temp ;
+                       singlist->length -- ;
+                       singlist->tail->next = singlist->head ;
+
+                       singlist->next = rings ;
+                       rings = singlist ;
+               }
+               else
+               {
+                       singlist->next = nlist ;
+                       nlist = singlist ;
+               }
+
+       }
+
+       // Append list2 and nlist to the end of list1 
+       tlist = list1 ;
+       if ( tlist != NULL )
+       {
+               while ( tlist->next != NULL )
+               {
+                       tlist = tlist->next ;
+               }
+               tlist->next = list2 ;
+       }
+       else
+       {
+               tlist = list2 ;
+               list1 = list2 ;
+       }
+
+       if ( tlist != NULL )
+       {
+               while ( tlist->next != NULL )
+               {
+                       tlist = tlist->next ;
+               }
+               tlist->next = nlist ;
+       }
+       else
+       {
+               tlist = nlist ;
+               list1 = nlist ;
+       }
+
+}
+
+PathList* Octree::combineSinglePath( PathList*& head1, PathList* pre1, PathList*& list1, PathList*& head2, PathList* pre2, PathList*& list2 )
+{
+       if ( isEqual( list1->head, list2->head ) || isEqual( list1->tail, list2->tail ) )
+       {
+               // Reverse the list
+               if ( list1->length < list2->length )
+               {
+                       // Reverse list1
+                       PathElement* prev = list1->head ;
+                       PathElement* next = prev->next ;
+                       prev->next = NULL ;
+                       while ( next != NULL )
+                       {
+                               PathElement* tnext = next->next ;
+                               next->next = prev ;
+
+                               prev = next ;
+                               next = tnext ;
+                       }
+
+                       list1->tail = list1->head ;
+                       list1->head = prev ;
+               }
+               else
+               {
+                       // Reverse list2
+                       PathElement* prev = list2->head ;
+                       PathElement* next = prev->next ;
+                       prev->next = NULL ;
+                       while ( next != NULL )
+                       {
+                               PathElement* tnext = next->next ;
+                               next->next = prev ;
+
+                               prev = next ;
+                               next = tnext ;
+                       }
+
+                       list2->tail = list2->head ;
+                       list2->head = prev ;
+               }
+       }       
+       
+       if ( isEqual( list1->head, list2->tail ) )
+       {
+
+               // Easy case
+               PathElement* temp = list1->head->next ;
+               delete list1->head ;
+               list2->tail->next = temp ;
+
+               PathList* nlist = new PathList ;
+               nlist->length = list1->length + list2->length - 1 ;
+               nlist->head = list2->head ;
+               nlist->tail = list1->tail ;
+               nlist->next = NULL ;
+
+               deletePath( head1, pre1, list1 ) ;
+               deletePath( head2, pre2, list2 ) ;
+
+               return nlist ;
+       } 
+       else if ( isEqual( list1->tail, list2->head ) )
+       {
+               // Easy case
+               PathElement* temp = list2->head->next ;
+               delete list2->head ;
+               list1->tail->next = temp ;
+
+               PathList* nlist = new PathList ;
+               nlist->length = list1->length + list2->length - 1 ;
+               nlist->head = list1->head ;
+               nlist->tail = list2->tail ;
+               nlist->next = NULL ;
+
+               deletePath( head1, pre1, list1 ) ;
+               deletePath( head2, pre2, list2 ) ;
+
+               return nlist ;
+       }
+
+       return NULL ;
+}
+
+void Octree::deletePath( PathList*& head, PathList* pre, PathList*& curr )
+{
+       PathList* temp = curr ;
+       curr = temp->next ;
+       delete temp ;
+
+       if ( pre == NULL )
+       {
+               head = curr ;
+       }
+       else
+       {
+               pre->next = curr ;
+       }
+}
+
+void Octree::printElement( PathElement* ele )
+{
+       if ( ele != NULL )
+       {
+               dc_printf( " (%d %d %d)", ele->pos[0], ele->pos[1], ele->pos[2] ) ;
+       }
+}
+
+void Octree::printPath( PathList* path )
+{
+       PathElement* n = path->head;
+       int same = 0 ;
+
+#if DC_DEBUG
+       int len = ( dimen >> maxDepth ) ;
+#endif
+       while ( n && ( same == 0 || n != path->head ) )
+       {
+               same ++ ;
+               dc_printf( " (%d %d %d)", n->pos[0] / len, n->pos[1] / len, n->pos[2] / len ) ;
+               n = n->next ;
+       }
+
+       if ( n == path->head )
+       {
+               dc_printf(" Ring!\n") ;
+       }
+       else
+       {
+               dc_printf(" %p end!\n", n) ;
+       }
+}
+
+void Octree::printPath( PathElement* path )
+{
+       PathElement *n = path;
+       int same = 0 ;
+#if DC_DEBUG
+       int len = ( dimen >> maxDepth ) ; 
+#endif
+       while ( n && ( same == 0 || n != path ) )
+       {
+               same ++ ;
+               dc_printf( " (%d %d %d)", n->pos[0] / len, n->pos[1] / len, n->pos[2] / len ) ;
+               n = n->next ;
+       }
+
+       if ( n == path )
+       {
+               dc_printf(" Ring!\n") ;
+       }
+       else
+       {
+               dc_printf(" %p end!\n", n) ;
+       }
+
+}
+
+
+void Octree::printPaths( PathList* path )
+{
+       PathList* iter = path ;
+       int i = 0 ;
+       while ( iter != NULL )
+       {
+               dc_printf("Path %d:\n", i) ;
+               printPath( iter ) ;
+               iter = iter->next ;
+               i ++ ;
+       }
+}
+
+UCHAR* Octree::patch( UCHAR* node, int st[3], int len, PathList* rings )
+{
+#ifdef IN_DEBUG_MODE
+       dc_printf("Call to PATCH with rings: \n");
+       printPaths( rings ) ;
+#endif
+
+       /* Do nothing but couting 
+       PathList* tlist = rings ;
+       PathList* ttlist ;
+       PathElement* telem, * ttelem ;
+       while ( tlist!= NULL )
+       {
+               // printPath( tlist ) ;
+               this->numRings ++ ;
+               this->totRingLengths += tlist->length ;
+               if ( tlist->length > this->maxRingLength )
+               {
+                       this->maxRingLength = tlist->length ;
+               }
+               ttlist = tlist ;
+               tlist = tlist->next ;
+       }
+       return node ;
+       */
+       
+
+       /* Pass onto separate calls in each direction */
+       UCHAR* newnode = node ;
+       if ( len == mindimen )
+       {
+               dc_printf("Error! should have no list by now.\n") ;
+               exit(0) ;
+       }
+       
+       // YZ plane
+       PathList* xlists[2] ;
+       newnode = patchSplit( newnode, st, len, rings, 0, xlists[0], xlists[1] ) ;
+       
+       // XZ plane
+       PathList* ylists[4] ;
+       newnode = patchSplit( newnode, st, len, xlists[0], 1, ylists[0], ylists[1] ) ;
+       newnode = patchSplit( newnode, st, len, xlists[1], 1, ylists[2], ylists[3] ) ;
+       
+       // XY plane
+       PathList* zlists[8] ;
+       newnode = patchSplit( newnode, st, len, ylists[0], 2, zlists[0], zlists[1] ) ;
+       newnode = patchSplit( newnode, st, len, ylists[1], 2, zlists[2], zlists[3] ) ;
+       newnode = patchSplit( newnode, st, len, ylists[2], 2, zlists[4], zlists[5] ) ;
+       newnode = patchSplit( newnode, st, len, ylists[3], 2, zlists[6], zlists[7] ) ;
+       
+       // Recur
+       len >>= 1 ;
+       int count = 0 ;
+       for ( int i = 0 ; i < 8 ; i ++ )
+       {
+               if ( zlists[i] != NULL )
+               {
+                       int nori[3] = { 
+                               st[0] + len * vertmap[i][0] , 
+                               st[1] + len * vertmap[i][1] , 
+                               st[2] + len * vertmap[i][2] } ;
+                       patch( getChild( newnode , count ), nori, len, zlists[i] ) ;
+               }
+
+               if ( hasChild( newnode, i ) )
+               {
+                       count ++ ;
+               }
+       }
+#ifdef IN_DEBUG_MODE
+       dc_printf("Return from PATCH\n") ;
+#endif
+       return newnode ;
+       
+}
+
+
+UCHAR* Octree::patchSplit( UCHAR* node, int st[3], int len, PathList* rings, int dir, PathList*& nrings1, PathList*& nrings2 )
+{
+#ifdef IN_DEBUG_MODE
+       dc_printf("Call to PATCHSPLIT with direction %d and rings: \n", dir);
+       printPaths( rings ) ;
+#endif
+
+       UCHAR* newnode = node ;
+       nrings1 = NULL ;
+       nrings2 = NULL ;
+       PathList* tmp ;
+       while ( rings != NULL )
+       {
+               // Process this ring
+               newnode = patchSplitSingle( newnode, st, len, rings->head, dir, nrings1, nrings2 ) ;
+               
+               // Delete this ring from the group
+               tmp = rings ;
+               rings = rings->next ;
+               delete tmp ;
+       }
+
+#ifdef IN_DEBUG_MODE
+       dc_printf("Return from PATCHSPLIT with \n");
+       dc_printf("Rings gourp 1:\n") ;
+       printPaths( nrings1 ) ;
+       dc_printf("Rings group 2:\n") ;
+       printPaths( nrings2 ) ;
+#endif
+
+       return newnode ;
+}
+
+UCHAR* Octree::patchSplitSingle( UCHAR* node, int st[3], int len, PathElement* head, int dir, PathList*& nrings1, PathList*& nrings2 )
+{
+#ifdef IN_DEBUG_MODE
+       dc_printf("Call to PATCHSPLITSINGLE with direction %d and path: \n", dir );
+       printPath( head ) ;
+#endif
+
+       UCHAR* newnode = node ;
+
+       if ( head == NULL )
+       {
+#ifdef IN_DEBUG_MODE
+               dc_printf("Return from PATCHSPLITSINGLE with head==NULL.\n") ;
+#endif
+               return newnode;
+       }
+       else
+       {
+               // printPath( head ) ;
+       }
+       
+       // Walk along the ring to find pair of intersections
+       PathElement* pre1 = NULL ;
+       PathElement* pre2 = NULL ;
+       int side = findPair ( head, st[ dir ] + len / 2 , dir, pre1, pre2 ) ;
+       
+       /*
+       if ( pre1 == pre2 )
+       {
+               int edgelen = ( dimen >> maxDepth ) ;
+               dc_printf("Location: %d %d %d Direction: %d Reso: %d\n", st[0]/edgelen, st[1]/edgelen, st[2]/edgelen, dir, len/edgelen) ;
+               printPath( head ) ;
+               exit( 0 ) ;
+       }
+       */
+       
+       if ( side )
+       {
+               // Entirely on one side
+               PathList* nring = new PathList( ) ;
+               nring->head = head ;
+               
+               if ( side == -1 )
+               {
+                       nring->next = nrings1 ;
+                       nrings1 = nring ;
+               }
+               else
+               {
+                       nring->next = nrings2 ;
+                       nrings2 = nring ;
+               }
+       }
+       else
+       {
+               // Break into two parts
+               PathElement* nxt1 = pre1->next ;
+               PathElement* nxt2 = pre2->next ;
+               pre1->next = nxt2 ;
+               pre2->next = nxt1 ;
+
+               newnode = connectFace( newnode, st, len, dir, pre1, pre2 ) ;
+       
+               if ( isEqual( pre1, pre1->next ) )
+               {
+                       if ( pre1 == pre1->next )
+                       {
+                               delete pre1 ;
+                               pre1 = NULL ;
+                       }
+                       else
+                       {
+                               PathElement* temp = pre1->next ;
+                               pre1->next = temp->next ;
+                               delete temp ;
+                       }
+               }
+               if ( isEqual( pre2, pre2->next ) )
+               {
+                       if ( pre2 == pre2->next )
+                       {
+                               delete pre2 ;
+                               pre2 = NULL ;
+                       }
+                       else
+                       {
+                               PathElement* temp = pre2->next ;
+                               pre2->next = temp->next ;
+                               delete temp ;
+                       }
+               }
+
+               compressRing ( pre1 ) ;
+               compressRing ( pre2 ) ;
+               
+               // Recur
+               newnode = patchSplitSingle( newnode, st, len, pre1, dir, nrings1, nrings2 ) ;
+               newnode = patchSplitSingle( newnode, st, len, pre2, dir, nrings1, nrings2 ) ;
+               
+       }
+
+#ifdef IN_DEBUG_MODE
+       dc_printf("Return from PATCHSPLITSINGLE with \n");
+       dc_printf("Rings gourp 1:\n") ;
+       printPaths( nrings1 ) ;
+       dc_printf("Rings group 2:\n") ;
+       printPaths( nrings2 ) ;
+#endif
+
+       return newnode ;
+}
+
+UCHAR* Octree::connectFace( UCHAR* node, int st[3], int len, int dir, PathElement* f1, PathElement* f2 )
+{
+#ifdef IN_DEBUG_MODE
+       dc_printf("Call to CONNECTFACE with direction %d and length %d path: \n", dir, len );
+       dc_printf("Path (low side): \n" ) ;
+       printPath( f1 ) ;
+//     checkPath( f1 ) ;
+       dc_printf("Path (high side): \n" ) ;
+       printPath( f2 ) ;
+//     checkPath( f2 ) ;
+#endif
+
+       UCHAR* newnode = node ;
+
+       // Setup 2D 
+       int pos = st[ dir ] + len / 2 ;
+       int xdir = ( dir + 1 ) % 3 ;
+       int ydir = ( dir + 2 ) % 3 ;
+       
+       // Use existing intersections on f1 and f2
+       int x1, y1, x2, y2 ;
+       float p1, q1, p2, q2 ;
+
+       getFacePoint( f2->next, dir, x1, y1, p1, q1 ) ;
+       getFacePoint( f2, dir, x2, y2, p2, q2 ) ;
+       float dx = x2 + p2 - x1 - p1 ;
+       float dy = y2 + q2 - y1 - q1 ;
+       
+       // Do adapted Bresenham line drawing
+       float rx = p1, ry = q1 ;
+       int incx = 1, incy = 1 ; 
+       int lx = x1, ly = y1 ;
+       int hx = x2, hy = y2 ;
+       int choice ;
+       if ( x2 < x1 )
+       {
+               incx = -1 ;
+               rx = 1 - rx ;
+               lx = x2 ;
+               hx = x1 ;
+       }
+       if ( y2 < y1 )
+       {
+               incy = -1 ;
+               ry = 1 - ry ;
+               ly = y2 ;
+               hy = y1 ;
+       }
+       
+       float sx = dx * incx ;
+       float sy = dy * incy ;
+       
+       int ori[3] ;
+       ori[ dir ] = pos / mindimen ;
+       ori[ xdir ] = x1 ;
+       ori[ ydir ] = y1 ;
+       int walkdir ;
+       int inc ;
+       float alpha ;
+
+       PathElement* curEleN = f1 ;
+       PathElement* curEleP = f2->next ;
+       UCHAR *nodeN = NULL, *nodeP = NULL ;
+       UCHAR *curN = locateLeaf( newnode, len, f1->pos ) ;
+       UCHAR *curP = locateLeaf( newnode, len, f2->next->pos ) ;
+       if ( curN == NULL || curP == NULL )
+       {
+               exit(0) ;
+       }
+       int stN[3], stP[3] ;
+       int lenN, lenP ;
+       
+       /* Unused code, leaving for posterity
+
+       float stpt[3], edpt[3] ;
+       stpt[ dir ] = edpt[ dir ] = (float) pos ;
+       stpt[ xdir ] = ( x1 + p1 ) * mindimen ;
+       stpt[ ydir ] = ( y1 + q1 ) * mindimen ;
+       edpt[ xdir ] = ( x2 + p2 ) * mindimen ;
+       edpt[ ydir ] = ( y2 + q2 ) * mindimen ;
+       */
+       while( ori[ xdir ] != x2 || ori[ ydir ] != y2 )
+       {
+               int next ;
+               if ( sy * (1 - rx) > sx * (1 - ry) )
+               {
+                       choice = 1 ; 
+                       next = ori[ ydir ] + incy ;
+                       if ( next < ly || next > hy ) 
+                       {
+                               choice = 4 ;
+                               next = ori[ xdir ] + incx ;
+                       }
+               }
+               else
+               {
+                       choice = 2 ;
+                       next = ori[ xdir ] + incx ;
+                       if ( next < lx || next > hx ) 
+                       {
+                               choice = 3 ;
+                               next = ori[ ydir ] + incy ;
+                       }
+               }
+               
+               if ( choice & 1 )
+               {
+                       ori[ ydir ] = next ;
+                       if ( choice == 1 )
+                       {
+                               rx += ( sy == 0 ? 0 : (1 - ry) * sx / sy  ) ; 
+                               ry = 0 ;
+                       }
+                       
+                       walkdir = 2 ;
+                       inc = incy ;
+                       alpha = x2 < x1 ? 1 - rx : rx ;
+               }
+               else
+               {
+                       ori[ xdir ] = next ;
+                       if ( choice == 2 )
+                       {
+                               ry += ( sx == 0 ? 0 : (1 - rx) * sy / sx ) ;
+                               rx = 0 ;        
+                       }
+                       
+                       walkdir = 1 ;
+                       inc = incx ;
+                       alpha = y2 < y1 ? 1 - ry : ry ;
+               }
+               
+
+
+               // Get the exact location of the marcher
+               int nori[3] = { ori[0] * mindimen, ori[1] * mindimen, ori[2] * mindimen } ;
+               float spt[3] = { (float) nori[0], (float) nori[1], (float) nori[2] } ;
+               spt[ ( dir + ( 3 - walkdir ) ) % 3 ] += alpha * mindimen ;
+               if ( inc < 0 )
+               {
+                       spt[ ( dir + walkdir ) % 3 ] += mindimen ;
+               }
+               
+               // dc_printf("new x,y: %d %d\n", ori[ xdir ] / edgelen, ori[ ydir ] / edgelen ) ;
+               // dc_printf("nori: %d %d %d alpha: %f walkdir: %d\n", nori[0], nori[1], nori[2], alpha, walkdir ) ;
+               // dc_printf("%f %f %f\n", spt[0], spt[1], spt[2] ) ;
+
+               // Locate the current cells on both sides
+               newnode = locateCell( newnode, st, len, nori, dir, 1, nodeN, stN, lenN ) ;
+               newnode = locateCell( newnode, st, len, nori, dir, 0, nodeP, stP, lenP ) ;
+
+               updateParent( newnode, len, st ) ;
+
+               int flag = 0 ;
+               // Add the cells to the rings and fill in the patch
+               PathElement* newEleN ;
+               if ( curEleN->pos[0] != stN[0] || curEleN->pos[1] != stN[1] || curEleN->pos[2] != stN[2] )
+               {
+                       if ( curEleN->next->pos[0] != stN[0] || curEleN->next->pos[1] != stN[1] || curEleN->next->pos[2] != stN[2] )
+                       {
+                               newEleN = new PathElement ;
+                               newEleN->next = curEleN->next ;
+                               newEleN->pos[0] = stN[0] ;
+                               newEleN->pos[1] = stN[1] ;
+                               newEleN->pos[2] = stN[2] ;
+
+                               curEleN->next = newEleN ;
+                       }
+                       else
+                       {
+                               newEleN = curEleN->next ;
+                       }
+                       curN = patchAdjacent( newnode, len, curEleN->pos, curN, newEleN->pos, nodeN, walkdir, inc, dir, 1, alpha ) ;
+
+                       curEleN = newEleN ;
+                       flag ++ ;
+               }
+
+               PathElement* newEleP ;
+               if ( curEleP->pos[0] != stP[0] || curEleP->pos[1] != stP[1] || curEleP->pos[2] != stP[2] )
+               {
+                       if ( f2->pos[0] != stP[0] || f2->pos[1] != stP[1] || f2->pos[2] != stP[2] )
+                       {
+                               newEleP = new PathElement ;
+                               newEleP->next = curEleP ;
+                               newEleP->pos[0] = stP[0] ;
+                               newEleP->pos[1] = stP[1] ;
+                               newEleP->pos[2] = stP[2] ;
+
+                               f2->next = newEleP ;
+                       }
+                       else
+                       {
+                               newEleP = f2 ;
+                       }
+                       curP = patchAdjacent( newnode, len, curEleP->pos, curP, newEleP->pos, nodeP, walkdir, inc, dir, 0, alpha ) ;
+
+
+
+                       curEleP = newEleP ;
+                       flag ++ ;
+               }
+
+                       
+               /*
+               if ( flag == 0 )
+               {
+                       dc_printf("error: non-synchronized patching! at \n") ;
+               }
+               */
+       }
+
+#ifdef IN_DEBUG_MODE
+       dc_printf("Return from CONNECTFACE with \n");
+       dc_printf("Path (low side):\n") ;
+       printPath( f1 ) ;
+       checkPath( f1 ) ;
+       dc_printf("Path (high side):\n") ;
+       printPath( f2 ) ;
+       checkPath( f2 ) ;
+#endif
+
+
+       return newnode ;
+}
+
+UCHAR* Octree::patchAdjacent( UCHAR* node, int len, int st1[3], UCHAR* leaf1, int st2[3], UCHAR* leaf2, int walkdir, int inc, int dir, int side, float alpha )
+{
+#ifdef IN_DEBUG_MODE
+       dc_printf("Before patching.\n") ;
+       printInfo( st1 ) ;
+       printInfo( st2 ) ;
+       dc_printf("-----------------%d %d %d ; %d %d %d\n", st1[0], st2[1], st1[2], st2[0], st2[1], st2[2] ) ;
+#endif
+
+       // Get edge index on each leaf
+       int edgedir = ( dir + ( 3 - walkdir ) ) % 3 ;
+       int incdir = ( dir + walkdir ) % 3 ;
+       int ind1 = ( edgedir == 1 ? ( dir + 3 - edgedir ) % 3 - 1 : 2 - ( dir + 3 - edgedir ) % 3 ) ;
+       int ind2 = ( edgedir == 1 ? ( incdir + 3 - edgedir ) % 3 - 1 : 2 - ( incdir + 3 - edgedir ) % 3 ) ;
+
+       int eind1 = ( ( edgedir << 2 ) | ( side << ind1 ) | ( ( inc > 0 ? 1 : 0 ) << ind2 ) ) ;
+       int eind2 = ( ( edgedir << 2 ) | ( side << ind1 ) | ( ( inc > 0 ? 0 : 1 ) << ind2 ) ) ;
+
+#ifdef IN_DEBUG_MODE
+       dc_printf("Index 1: %d Alpha 1: %f Index 2: %d Alpha 2: %f\n", eind1, alpha, eind2, alpha ) ;
+       /*
+       if ( alpha < 0 || alpha > 1 )
+       {
+               dc_printf("Index 1: %d Alpha 1: %f Index 2: %d Alpha 2: %f\n", eind1, alpha, eind2, alpha ) ;
+               printInfo( st1 ) ;
+               printInfo( st2 ) ;
+       }
+       */
+#endif
+
+       // Flip edge parity
+       UCHAR* nleaf1 = flipEdge( leaf1, eind1, alpha ) ;
+       UCHAR* nleaf2 = flipEdge( leaf2, eind2, alpha ) ;
+
+       // Update parent link
+       updateParent( node, len, st1, nleaf1 ) ;
+       updateParent( node, len, st2, nleaf2 ) ;
+       // updateParent( nleaf1, mindimen, st1 ) ;
+       // updateParent( nleaf2, mindimen, st2 ) ;
+
+       /*
+       float m[3] ;
+       dc_printf("Adding new point: %f %f %f\n", spt[0], spt[1], spt[2] ) ;
+       getMinimizer( leaf1, m ) ;
+       dc_printf("Cell %d now has minimizer %f %f %f\n", leaf1, m[0], m[1], m[2] ) ;
+       getMinimizer( leaf2, m ) ;
+       dc_printf("Cell %d now has minimizer %f %f %f\n", leaf2, m[0], m[1], m[2] ) ;
+       */              
+
+#ifdef IN_DEBUG_MODE
+       dc_printf("After patching.\n") ;
+       printInfo( st1 ) ;
+       printInfo( st2 ) ;
+#endif
+       return nleaf2 ;
+}
+
+UCHAR* Octree::locateCell( UCHAR* node, int st[3], int len, int ori[3], int dir, int side, UCHAR*& rleaf, int rst[3], int& rlen )
+{
+#ifdef IN_DEBUG_MODE
+       // dc_printf("Call to LOCATECELL with node ") ;
+       // printNode( node ) ;
+#endif
+       UCHAR* newnode = node ;
+       int i ;
+       len >>= 1 ;
+       int ind = 0 ;
+       for ( i = 0 ; i < 3 ; i ++ )
+       {
+               ind <<= 1 ;
+               if ( i == dir && side == 1 )
+               {
+                       ind |= ( ori[ i ] <= ( st[ i ] + len ) ? 0 : 1 ) ;
+               }
+               else
+               {
+                       ind |= ( ori[ i ] < ( st[ i ] + len ) ? 0 : 1 ) ;
+               }
+       }
+
+#ifdef IN_DEBUG_MODE
+       // dc_printf("In LOCATECELL index of ori (%d %d %d) with dir %d side %d in st (%d %d %d, %d) is: %d\n",
+       //      ori[0], ori[1], ori[2], dir, side, st[0], st[1], st[2], len, ind ) ;
+#endif
+
+       rst[0] = st[0] + vertmap[ ind ][ 0 ] * len ;
+       rst[1] = st[1] + vertmap[ ind ][ 1 ] * len ;
+       rst[2] = st[2] + vertmap[ ind ][ 2 ] * len ;
+       
+       if ( hasChild( newnode, ind ) )
+       {
+               int count = getChildCount( newnode, ind ) ;
+               UCHAR* chd = getChild( newnode, count ) ;
+               if ( isLeaf( newnode, ind ) )
+               {
+                       rleaf = chd ;
+                       rlen = len ;
+               }
+               else
+               {
+                       // Recur
+                       setChild( newnode, count, locateCell( chd, rst, len, ori, dir, side, rleaf, rst, rlen ) ) ;
+               }
+       }
+       else
+       {
+               // Create a new child here
+               if ( len == this->mindimen )
+               {
+                       UCHAR* chd = createLeaf( 0 ) ;
+                       newnode = addChild( newnode, ind, chd, 1 ) ;
+                       rleaf = chd ;
+                       rlen = len ;
+               }
+               else
+               {
+                       // Subdivide the empty cube
+                       UCHAR* chd = createInternal( 0 ) ;
+                       newnode = addChild( newnode, ind, locateCell( chd, rst, len, ori, dir, side, rleaf, rst, rlen ), 0 ) ;
+               }
+       }
+       
+#ifdef IN_DEBUG_MODE
+       // dc_printf("Return from LOCATECELL with node ") ;
+       // printNode( newnode ) ;
+#endif
+       return newnode ;
+}
+
+void Octree::checkElement( PathElement* ele )
+{
+       /*
+       if ( ele != NULL && locateLeafCheck( ele->pos ) != ele->node )
+       {
+               dc_printf("Screwed! at pos: %d %d %d\n", ele->pos[0]>>minshift, ele->pos[1]>>minshift, ele->pos[2]>>minshift);
+               exit( 0 ) ;
+       }
+       */
+}
+
+void Octree::checkPath( PathElement* path )
+{
+       PathElement *n = path ;
+       int same = 0 ;
+       while ( n && ( same == 0 || n != path ) )
+       {
+               same ++ ;
+               checkElement( n ) ;
+               n = n->next ;
+       }
+
+}
+
+void Octree::testFacePoint( PathElement* e1, PathElement* e2 )
+{
+       int i ;
+       PathElement * e = NULL ;
+       for ( i = 0 ; i < 3 ; i ++ )
+       {
+               if ( e1->pos[i] != e2->pos[i] )
+               {
+                       if ( e1->pos[i] < e2->pos[i] )
+                       {
+                               e = e2 ;
+                       }
+                       else
+                       {
+                               e = e1 ;
+                       }
+                       break ;
+               }
+       }
+
+       int x, y ;
+       float p, q ;
+       dc_printf("Test.") ;
+       getFacePoint( e, i, x, y, p, q ) ;
+}
+
+void Octree::getFacePoint( PathElement* leaf, int dir, int& x, int& y, float& p, float& q )
+{
+       // Find average intersections
+       float avg[3] = {0, 0, 0} ;
+       float off[3] ;
+       int num = 0, num2 = 0 ;
+
+       UCHAR* leafnode = locateLeaf( leaf->pos ) ;
+       for ( int i = 0 ; i < 4 ; i ++ )
+       {
+               int edgeind = faceMap[ dir * 2 ][ i ] ;
+               int nst[3] ;
+               for ( int j = 0 ; j < 3 ; j ++ )
+               {
+                       nst[j] = leaf->pos[j] + mindimen * vertmap[ edgemap[ edgeind][ 0 ] ][ j ] ;
+               }
+
+               if ( getEdgeIntersectionByIndex( nst, edgeind / 4, off, 1 ) )
+               {
+                       avg[0] += off[0] ;
+                       avg[1] += off[1] ;
+                       avg[2] += off[2] ;
+                       num ++ ;
+               }
+               if ( getEdgeParity( leafnode, edgeind ) )
+               {
+                       num2 ++ ;
+               }
+       }
+       if ( num == 0 )
+       {
+               dc_printf("Wrong! dir: %d pos: %d %d %d num: %d\n", dir, leaf->pos[0]>>minshift, leaf->pos[1]>>minshift, leaf->pos[2]>>minshift, num2);
+               avg[0] = (float) leaf->pos[0] ;
+               avg[1] = (float) leaf->pos[1] ;
+               avg[2] = (float) leaf->pos[2] ;
+       }
+       else
+       {
+               
+               avg[0] /= num ;
+               avg[1] /= num ;
+               avg[2] /= num ;
+               
+               //avg[0] = (float) leaf->pos[0];
+               //avg[1] = (float) leaf->pos[1];
+               //avg[2] = (float) leaf->pos[2];
+       }
+       
+       int xdir = ( dir + 1 ) % 3 ;
+       int ydir = ( dir + 2 ) % 3 ;
+
+       float xf = avg[ xdir ] ;
+       float yf = avg[ ydir ] ;
+
+#ifdef IN_DEBUG_MODE
+       // Is it outside?
+       // PathElement* leaf = leaf1->len < leaf2->len ? leaf1 : leaf2 ;
+       /*
+       float* m = ( leaf == leaf1 ? m1 : m2 ) ;
+       if ( xf < leaf->pos[ xdir ] || 
+                yf < leaf->pos[ ydir ] ||
+                xf > leaf->pos[ xdir ] + leaf->len ||
+                yf > leaf->pos[ ydir ] + leaf->len)
+       {
+               dc_printf("Outside cube (%d %d %d), %d : %d %d %f %f\n", leaf->pos[ 0 ], leaf->pos[1], leaf->pos[2], leaf->len, 
+                                               pos, dir, xf, yf) ;
+
+               // For now, snap to cell
+               xf = m[ xdir ] ;
+               yf = m[ ydir ] ;
+       }
+       */
+
+       /*
+       if ( alpha < 0 || alpha > 1 ||
+                xf < leaf->pos[xdir] || xf > leaf->pos[xdir] + leaf->len || 
+                yf < leaf->pos[ydir] || yf > leaf->pos[ydir] + leaf->len )
+       {
+               dc_printf("Alpha: %f Address: %d and %d\n", alpha, leaf1->node, leaf2->node ) ;
+               dc_printf("GETFACEPOINT result: (%d %d %d) %d min: (%f %f %f) ;(%d %d %d) %d min: (%f %f %f).\n",
+                       leaf1->pos[0], leaf1->pos[1], leaf1->pos[2], leaf1->len, m1[0], m1[1], m1[2], 
+                       leaf2->pos[0], leaf2->pos[1], leaf2->pos[2], leaf2->len, m2[0], m2[1], m2[2]);
+               dc_printf("Face point at dir %d pos %d: %f %f\n", dir, pos, xf, yf ) ;
+       }
+       */
+#endif
+       
+
+       // Get the integer and float part
+       x = ( ( leaf->pos[ xdir ] ) >> minshift ) ;
+       y = ( ( leaf->pos[ ydir ] ) >> minshift ) ;
+
+       p = ( xf - leaf->pos[ xdir ] ) / mindimen ;
+       q = ( yf - leaf->pos[ ydir ] ) / mindimen ;
+
+
+#ifdef IN_DEBUG_MODE
+       dc_printf("Face point at dir %d : %f %f\n", dir, xf, yf ) ;
+#endif
+}
+
+int Octree::findPair( PathElement* head, int pos, int dir, PathElement*& pre1, PathElement*& pre2 )
+{
+       int side = getSide ( head, pos, dir ) ;
+       PathElement* cur = head ;
+       PathElement* anchor ;
+       PathElement* ppre1, *ppre2 ;
+       
+       // Start from this face, find a pair
+       anchor = cur ;
+       ppre1 = cur ;
+       cur = cur->next ;
+       while ( cur != anchor && ( getSide( cur, pos, dir ) == side ) )
+       {
+               ppre1 = cur ;
+               cur = cur->next ;
+       }
+       if ( cur == anchor )
+       {
+               // No pair found
+               return side ;
+       }
+       
+       side = getSide( cur, pos, dir ) ;
+       ppre2 = cur ;
+       cur = cur->next ;
+       while ( getSide( cur, pos, dir ) == side )
+       {
+               ppre2 = cur ;
+               cur = cur->next ;
+       }
+       
+       
+       // Switch pre1 and pre2 if we start from the higher side
+       if ( side == -1 )
+       {
+               cur = ppre1 ;
+               ppre1 = ppre2 ;
+               ppre2 = cur ;
+       }
+
+       pre1 = ppre1 ;
+       pre2 = ppre2 ;
+       
+       return 0 ;
+}
+
+int Octree::getSide( PathElement* e, int pos, int dir )
+{
+       return ( e->pos[ dir ] < pos ? -1 : 1 ) ;
+}
+
+int Octree::isEqual( PathElement* e1, PathElement* e2 )
+{
+       return ( e1->pos[0] == e2->pos[0] && e1->pos[1] == e2->pos[1] && e1->pos[2] == e2->pos[2] ) ;
+}
+
+void Octree::compressRing( PathElement*& ring )
+{
+       if ( ring == NULL )
+       {
+               return ;
+       }
+#ifdef IN_DEBUG_MODE
+       dc_printf("Call to COMPRESSRING with path: \n" );
+       printPath( ring ) ;
+#endif
+
+       PathElement* cur = ring->next->next ;
+       PathElement* pre = ring->next ;
+       PathElement* prepre = ring ;
+       PathElement* anchor = prepre ;
+       
+       do
+       {
+               while ( isEqual( cur, prepre ) )
+               {
+                       // Delete
+                       if ( cur == prepre )
+                       {
+                               // The ring has shrinked to a point
+                               delete pre ;
+                               delete cur ;
+                               anchor = NULL ;
+                               break ;
+                       }
+                       else
+                       {
+                               prepre->next = cur->next ;
+                               delete pre ;
+                               delete cur ;
+                               pre = prepre->next ;
+                               cur = pre->next ;
+                               anchor = prepre ;
+                       }
+               }
+               
+               if ( anchor == NULL )
+               {
+                       break ;
+               }
+               
+               prepre = pre ;
+               pre = cur ;
+               cur = cur->next ;
+       } while ( prepre != anchor ) ;
+       
+       ring = anchor ;
+
+#ifdef IN_DEBUG_MODE
+       dc_printf("Return from COMPRESSRING with path: \n" );
+       printPath( ring ) ;
+#endif
+}
+
+void Octree::buildSigns( )
+{
+       // First build a lookup table
+       // dc_printf("Building up look up table...\n") ;
+       int size = 1 << 12 ;
+       unsigned char table[ 1 << 12 ] ;
+       for ( int i = 0 ; i < size ; i ++ )
+       {
+               table[i] = 0 ;
+       }
+       for ( int i = 0 ; i < 256 ; i ++ )
+       {
+               int ind = 0 ;
+               for ( int j = 11 ; j >= 0 ; j -- )
+               {
+                       ind <<= 1 ;
+                       if ( ( ( i >> edgemap[j][0] ) & 1 ) ^ ( ( i >> edgemap[j][1] ) & 1 ) )
+                       {
+                               ind |= 1 ;
+                       }
+               }
+
+               table[ ind ] = i ;
+       }
+
+       // Next, traverse the grid
+       int sg = 1 ;
+       int cube[8] ;
+       buildSigns( table, this->root, 0, sg, cube ) ;
+}
+
+void Octree::buildSigns( unsigned char table[], UCHAR* node, int isLeaf, int sg, int rvalue[8] )
+{
+       if ( node == NULL )
+       {
+               for ( int i = 0 ; i < 8 ; i ++ )
+               {
+                       rvalue[i] = sg ;
+               }
+               return ;
+       }
+
+       if ( isLeaf == 0 )
+       {
+               // Internal node
+               UCHAR* chd[8] ;
+               int leaf[8] ;
+               fillChildren( node, chd, leaf ) ;
+
+               // Get the signs at the corners of the first cube
+               rvalue[0] = sg ;
+               int oris[8] ;
+               buildSigns( table, chd[0], leaf[0], sg, oris ) ;
+
+               // Get the rest
+               int cube[8] ;
+               for ( int i = 1 ; i < 8 ; i ++ )
+               {
+                       buildSigns( table, chd[i], leaf[i], oris[i], cube ) ;
+                       rvalue[i] = cube[i] ;
+               }
+
+       }
+       else
+       {
+               // Leaf node
+               generateSigns( node, table, sg ) ;
+
+               for ( int i = 0 ; i < 8 ; i ++ )
+               {
+                       rvalue[i] = getSign( node, i ) ;
+               }
+       }
+}
+
+void Octree::floodFill( )
+{
+       // int threshold = (int) ((dimen/mindimen) * (dimen/mindimen) * 0.5f) ;
+       int st[3] = { 0, 0, 0 } ;
+
+       // First, check for largest component
+       // size stored in -threshold
+       this->clearProcessBits( root, maxDepth ) ;
+       int threshold = this->floodFill( root, st, dimen, maxDepth, 0 ) ;
+
+       // Next remove
+       dc_printf("Largest component: %d\n", threshold);
+       threshold *= thresh ;
+       dc_printf("Removing all components smaller than %d\n", threshold) ;
+
+       int st2[3] = { 0, 0, 0 } ;
+       this->clearProcessBits( root, maxDepth ) ;
+       this->floodFill( root, st2, dimen, maxDepth, threshold ) ;
+
+}
+
+void Octree::clearProcessBits( UCHAR* node, int height )
+{
+       int i;
+
+       if ( height == 0 )
+       {
+               // Leaf cell, 
+               for ( i = 0 ; i < 12 ; i ++ )
+               {
+                       setOutProcess( node, i ) ;
+               }
+       }
+       else
+       {
+               // Internal cell, recur
+               int count = 0 ;
+               for ( i = 0 ; i < 8 ; i ++ )
+               {
+                       if ( hasChild( node, i ) )
+                       {
+                               clearProcessBits( getChild( node, count ), height - 1 ) ;
+                               count ++ ;
+                       }
+               }
+       }       
+}
+
+/*
+void Octree::floodFill( UCHAR* node, int st[3], int len, int height, int threshold )
+{
+       int i, j;
+
+       if ( height == 0 )
+       {
+               // Leaf cell, 
+               int par, inp ;
+
+               // Test if the leaf has intersection edges
+               for ( i = 0 ; i < 12 ; i ++ )
+               {
+                       par = getEdgeParity( node, i ) ;
+                       inp = isInProcess( node, i ) ;
+
+                       if ( par == 1 && inp == 0 )
+                       {
+                               // Intersection edge, hasn't been processed
+                               // Let's start filling
+                               GridQueue* queue = new GridQueue() ;
+                               int total = 1 ;
+
+                               // Set to in process
+                               int mst[3] ;
+                               mst[0] = st[0] + vertmap[edgemap[i][0]][0] * len ;
+                               mst[1] = st[1] + vertmap[edgemap[i][0]][1] * len ;
+                               mst[2] = st[2] + vertmap[edgemap[i][0]][2] * len;
+                               int mdir = i / 4 ;
+                               setInProcessAll( mst, mdir ) ;
+
+                               // Put this edge into queue
+                               queue->pushQueue( mst, mdir ) ;
+
+                               // Queue processing
+                               int nst[3], dir ;
+                               while ( queue->popQueue( nst, dir ) == 1 )
+                               {
+                                       // dc_printf("nst: %d %d %d, dir: %d\n", nst[0]/mindimen, nst[1]/mindimen, nst[2]/mindimen, dir) ;
+                                       // locations
+                                       int stMask[3][3] = {
+                                               { 0, 0 - len, 0 - len },
+                                               { 0 - len, 0, 0 - len },
+                                               { 0 - len, 0 - len, 0 }
+                                       };
+                                       int cst[2][3] ;
+                                       for ( j = 0 ; j < 3 ; j ++ )
+                                       {
+                                               cst[0][j] = nst[j] ;
+                                               cst[1][j] = nst[j] + stMask[ dir ][ j ] ;
+                                       }
+
+                                       // cells 
+                                       UCHAR* cs[2] ;
+                                       for ( j = 0 ; j < 2 ; j ++ )
+                                       {
+                                               cs[ j ] = locateLeaf( cst[j] ) ;
+                                       }
+
+                                       // Middle sign
+                                       int s = getSign( cs[0], 0 ) ;
+
+                                       // Masks
+                                       int fcCells[4] = {1,0,1,0};
+                                       int fcEdges[3][4][3] = {
+                                               {{9,2,11},{8,1,10},{5,1,7},{4,2,6}},
+                                               {{10,6,11},{8,5,9},{1,5,3},{0,6,2}},
+                                               {{6,10,7},{4,9,5},{2,9,3},{0,10,1}}
+                                       };
+
+                                       // Search for neighboring connected intersection edges
+                                       for ( int find = 0 ; find < 4 ; find ++ )
+                                       {
+                                               int cind = fcCells[find] ;
+                                               int eind, edge ;
+                                               if ( s == 0 )
+                                               {
+                                                       // Original order
+                                                       for ( eind = 0 ; eind < 3 ; eind ++ )
+                                                       {
+                                                               edge = fcEdges[dir][find][eind] ;
+                                                               if ( getEdgeParity( cs[cind], edge ) == 1 )
+                                                               {
+                                                                       break ;
+                                                               }
+                                                       }
+                                               }
+                                               else
+                                               {
+                                                       // Inverse order
+                                                       for ( eind = 2 ; eind >= 0 ; eind -- )
+                                                       {
+                                                               edge = fcEdges[dir][find][eind] ;
+                                                               if ( getEdgeParity( cs[cind], edge ) == 1 )
+                                                               {
+                                                                       break ;
+                                                               }
+                                                       }
+                                               }
+                                               
+                                               if ( eind == 3 || eind == -1 )
+                                               {
+                                                       dc_printf("Wrong! this is not a consistent sign. %d\n", eind );
+                                               }
+                                               else 
+                                               {
+                                                       int est[3] ;
+                                                       est[0] = cst[cind][0] + vertmap[edgemap[edge][0]][0] * len ;
+                                                       est[1] = cst[cind][1] + vertmap[edgemap[edge][0]][1] * len ;
+                                                       est[2] = cst[cind][2] + vertmap[edgemap[edge][0]][2] * len ;
+                                                       int edir = edge / 4 ;
+                                                       
+                                                       if ( isInProcess( cs[cind], edge ) == 0 )
+                                                       {
+                                                               setInProcessAll( est, edir ) ;
+                                                               queue->pushQueue( est, edir ) ;
+                                                               // dc_printf("Pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ;
+                                                               total ++ ;
+                                                       }
+                                                       else
+                                                       {
+                                                               // dc_printf("Processed, not pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ;
+                                                       }
+                                               }
+                                               
+                                       }
+
+                               }
+
+                               dc_printf("Size of component: %d ", total) ;
+
+                               if ( total > threshold )
+                               {
+                                       dc_printf("Maintained.\n") ;
+                                       continue ;
+                               }
+                               dc_printf("Less then %d, removing...\n", threshold) ;
+
+                               // We have to remove this noise
+
+                               // Flip parity
+                               // setOutProcessAll( mst, mdir ) ;
+                               flipParityAll( mst, mdir ) ;
+
+                               // Put this edge into queue
+                               queue->pushQueue( mst, mdir ) ;
+
+                               // Queue processing
+                               while ( queue->popQueue( nst, dir ) == 1 )
+                               {
+                                       // dc_printf("nst: %d %d %d, dir: %d\n", nst[0]/mindimen, nst[1]/mindimen, nst[2]/mindimen, dir) ;
+                                       // locations
+                                       int stMask[3][3] = {
+                                               { 0, 0 - len, 0 - len },
+                                               { 0 - len, 0, 0 - len },
+                                               { 0 - len, 0 - len, 0 }
+                                       };
+                                       int cst[2][3] ;
+                                       for ( j = 0 ; j < 3 ; j ++ )
+                                       {
+                                               cst[0][j] = nst[j] ;
+                                               cst[1][j] = nst[j] + stMask[ dir ][ j ] ;
+                                       }
+
+                                       // cells 
+                                       UCHAR* cs[2] ;
+                                       for ( j = 0 ; j < 2 ; j ++ )
+                                       {
+                                               cs[ j ] = locateLeaf( cst[j] ) ;
+                                       }
+
+                                       // Middle sign
+                                       int s = getSign( cs[0], 0 ) ;
+
+                                       // Masks
+                                       int fcCells[4] = {1,0,1,0};
+                                       int fcEdges[3][4][3] = {
+                                               {{9,2,11},{8,1,10},{5,1,7},{4,2,6}},
+                                               {{10,6,11},{8,5,9},{1,5,3},{0,6,2}},
+                                               {{6,10,7},{4,9,5},{2,9,3},{0,10,1}}
+                                       };
+
+                                       // Search for neighboring connected intersection edges
+                                       for ( int find = 0 ; find < 4 ; find ++ )
+                                       {
+                                               int cind = fcCells[find] ;
+                                               int eind, edge ;
+                                               if ( s == 0 )
+                                               {
+                                                       // Original order
+                                                       for ( eind = 0 ; eind < 3 ; eind ++ )
+                                                       {
+                                                               edge = fcEdges[dir][find][eind] ;
+                                                               if ( isInProcess( cs[cind], edge ) == 1 )
+                                                               {
+                                                                       break ;
+                                                               }
+                                                       }
+                                               }
+                                               else
+                                               {
+                                                       // Inverse order
+                                                       for ( eind = 2 ; eind >= 0 ; eind -- )
+                                                       {
+                                                               edge = fcEdges[dir][find][eind] ;
+                                                               if ( isInProcess( cs[cind], edge ) == 1 )
+                                                               {
+                                                                       break ;
+                                                               }
+                                                       }
+                                               }
+                                               
+                                               if ( eind == 3 || eind == -1 )
+                                               {
+                                                       dc_printf("Wrong! this is not a consistent sign. %d\n", eind );
+                                               }
+                                               else 
+                                               {
+                                                       int est[3] ;
+                                                       est[0] = cst[cind][0] + vertmap[edgemap[edge][0]][0] * len ;
+                                                       est[1] = cst[cind][1] + vertmap[edgemap[edge][0]][1] * len ;
+                                                       est[2] = cst[cind][2] + vertmap[edgemap[edge][0]][2] * len ;
+                                                       int edir = edge / 4 ;
+                                                       
+                                                       if ( getEdgeParity( cs[cind], edge ) == 1 )
+                                                       {
+                                                               flipParityAll( est, edir ) ;
+                                                               queue->pushQueue( est, edir ) ;
+                                                               // dc_printf("Pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ;
+                                                               total ++ ;
+                                                       }
+                                                       else
+                                                       {
+                                                               // dc_printf("Processed, not pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ;
+                                                       }
+                                               }
+                                               
+                                       }
+
+                               }
+
+                       }
+               }
+       }
+       else
+       {
+               // Internal cell, recur
+               int count = 0 ;
+               len >>= 1 ;
+               for ( i = 0 ; i < 8 ; i ++ )
+               {
+                       if ( hasChild( node, i ) )
+                       {
+                               int nst[3] ;
+                               nst[0] = st[0] + vertmap[i][0] * len ;
+                               nst[1] = st[1] + vertmap[i][1] * len ;
+                               nst[2] = st[2] + vertmap[i][2] * len ;
+                               
+                               floodFill( getChild( node, count ), nst, len, height - 1, threshold ) ;
+                               count ++ ;
+                       }
+               }
+       }
+}
+*/
+
+int Octree::floodFill( UCHAR* node, int st[3], int len, int height, int threshold )
+{
+       int i, j;
+       int maxtotal = 0 ;
+
+       if ( height == 0 )
+       {
+               // Leaf cell, 
+               int par, inp ;
+
+               // Test if the leaf has intersection edges
+               for ( i = 0 ; i < 12 ; i ++ )
+               {
+                       par = getEdgeParity( node, i ) ;
+                       inp = isInProcess( node, i ) ;
+
+                       if ( par == 1 && inp == 0 )
+                       {
+                               // Intersection edge, hasn't been processed
+                               // Let's start filling
+                               GridQueue* queue = new GridQueue() ;
+                               int total = 1 ;
+
+                               // Set to in process
+                               int mst[3] ;
+                               mst[0] = st[0] + vertmap[edgemap[i][0]][0] * len ;
+                               mst[1] = st[1] + vertmap[edgemap[i][0]][1] * len ;
+                               mst[2] = st[2] + vertmap[edgemap[i][0]][2] * len;
+                               int&n